初始化v1

This commit is contained in:
2025-08-03 00:11:15 +08:00
commit b88c8b8afa
171 changed files with 22353 additions and 0 deletions

15
api/hello/hello.go Normal file
View File

@@ -0,0 +1,15 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package hello
import (
"context"
"nl-video-api/api/hello/v1"
)
type IHelloV1 interface {
Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error)
}

12
api/hello/v1/hello.go Normal file
View File

@@ -0,0 +1,12 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
type HelloReq struct {
g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"`
}
type HelloRes struct {
g.Meta `mime:"text/html" example:"string"`
}

80
api/middleware/auth.go Normal file
View File

@@ -0,0 +1,80 @@
package middleware
import (
"nl-video-api/internal/consts"
"nl-video-api/utility/jwt"
"nl-video-api/utility/response"
"strings"
"github.com/gogf/gf/v2/net/ghttp"
)
// Auth JWT认证中间件
func Auth(r *ghttp.Request) {
// 获取Authorization头
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
response.Error(r, response.CodeUnauthorized, "请提供认证令牌")
return
}
// 检查Bearer前缀
if !strings.HasPrefix(authHeader, "Bearer ") {
response.Error(r, response.CodeUnauthorized, "认证令牌格式错误")
return
}
// 提取token
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
if tokenString == "" {
response.Error(r, response.CodeUnauthorized, "认证令牌不能为空")
return
}
// 解析token
claims, err := jwt.ParseToken(tokenString)
if err != nil {
response.Error(r, response.CodeTokenInvalid, "认证令牌无效")
return
}
// 将用户信息存储到上下文
r.SetCtxVar("user_id", claims.UserID)
r.SetCtxVar("username", claims.Username)
r.SetCtxVar("user_type", claims.UserType)
r.Middleware.Next()
}
// AdminAuth 管理员认证中间件
func AdminAuth(r *ghttp.Request) {
// 先执行基础认证
Auth(r)
if r.Response.Status >= 400 {
return
}
// 检查用户类型
userType := r.GetCtxVar("user_type").String()
if userType != consts.UserTypeAdmin {
response.Error(r, response.CodeForbidden, "需要管理员权限")
return
}
r.Middleware.Next()
}
// OptionalAuth 可选认证中间件(不强制要求登录)
func OptionalAuth(r *ghttp.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
if claims, err := jwt.ParseToken(tokenString); err == nil {
r.SetCtxVar("user_id", claims.UserID)
r.SetCtxVar("username", claims.Username)
r.SetCtxVar("user_type", claims.UserType)
}
}
r.Middleware.Next()
}

19
api/middleware/cors.go Normal file
View File

@@ -0,0 +1,19 @@
package middleware
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// CORS 跨域处理中间件
func CORS(r *ghttp.Request) {
// 设置CORS头
r.Response.CORSDefault()
// 处理预检请求
if r.Method == "OPTIONS" {
r.Response.WriteHeader(200)
return
}
r.Middleware.Next()
}

54
api/middleware/log.go Normal file
View File

@@ -0,0 +1,54 @@
package middleware
import (
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
)
// RequestLog 请求日志中间件
func RequestLog(r *ghttp.Request) {
start := time.Now()
// 记录请求开始
g.Log().Info(r.Context(),
"请求开始",
"method", r.Method,
"uri", r.RequestURI,
"ip", r.GetClientIp(),
"user_agent", r.Header.Get("User-Agent"),
)
r.Middleware.Next()
// 记录请求结束
duration := time.Since(start)
g.Log().Info(r.Context(),
"请求结束",
"method", r.Method,
"uri", r.RequestURI,
"status", r.Response.Status,
"duration", duration.String(),
"ip", r.GetClientIp(),
)
}
// ErrorLog 错误日志中间件
func ErrorLog(r *ghttp.Request) {
r.Middleware.Next()
// 如果有错误,记录详细信息
if r.Response.Status >= 400 {
g.Log().Error(r.Context(),
"请求错误",
"method", r.Method,
"uri", r.RequestURI,
"status", r.Response.Status,
"ip", r.GetClientIp(),
"user_agent", r.Header.Get("User-Agent"),
"time", gtime.Now().String(),
)
}
}

View File

@@ -0,0 +1,221 @@
package middleware
import (
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service/auth"
"nl-video-api/utility/jwt"
"nl-video-api/utility/response"
)
// PermissionMiddleware 权限验证中间件
func PermissionMiddleware(r *ghttp.Request) {
// 获取请求路径和方法
apiPath := r.URL.Path
method := r.Method
// 跳过不需要权限验证的路径
skipPaths := []string{
"/api/v1/auth/login",
"/api/v1/auth/register",
"/api/v1/admin/login",
"/api/v1/admin/register",
}
for _, skipPath := range skipPaths {
if apiPath == skipPath {
r.Middleware.Next()
return
}
}
// 获取Token
token := r.Header.Get("Authorization")
if token == "" {
response.Error(r, 1002, "请先登录")
return
}
// 移除Bearer前缀
if strings.HasPrefix(token, "Bearer ") {
token = strings.TrimPrefix(token, "Bearer ")
}
// 验证Token
claims, err := jwt.ParseToken(token)
if err != nil {
response.Error(r, 1003, "Token无效")
return
}
// 获取用户ID
userId := int(claims.UserID)
if userId <= 0 {
response.Error(r, 1003, "Token无效")
return
}
// 检查API权限
hasPermission, err := auth.Permission.CheckApiPermission(r.Context(), userId, apiPath, method)
if err != nil {
g.Log().Errorf(r.Context(), "权限检查失败: %v", err)
response.Error(r, 1004, "权限检查失败")
return
}
if !hasPermission {
response.Error(r, 1004, "没有访问权限")
return
}
// 将用户ID存储到上下文中
r.SetCtxVar("user_id", userId)
r.Middleware.Next()
}
// RolePermissionMiddleware 角色权限验证中间件
func RolePermissionMiddleware(requiredRole string) func(r *ghttp.Request) {
return func(r *ghttp.Request) {
// 获取Token
token := r.Header.Get("Authorization")
if token == "" {
response.Error(r, 1002, "请先登录")
return
}
// 移除Bearer前缀
if strings.HasPrefix(token, "Bearer ") {
token = strings.TrimPrefix(token, "Bearer ")
}
// 验证Token
claims, err := jwt.ParseToken(token)
if err != nil {
response.Error(r, 1003, "Token无效")
return
}
// 获取用户角色
userRole := claims.UserType
if userRole == "" {
response.Error(r, 1004, "用户角色信息无效")
return
}
// 检查角色权限
if userRole != requiredRole && userRole != "super_admin" {
response.Error(r, 1004, "没有访问权限")
return
}
r.Middleware.Next()
}
}
// AdminPermissionMiddleware 管理员权限验证中间件
func AdminPermissionMiddleware(r *ghttp.Request) {
// 获取Token
token := r.Header.Get("Authorization")
if token == "" {
response.Error(r, 1002, "请先登录")
return
}
// 移除Bearer前缀
if strings.HasPrefix(token, "Bearer ") {
token = strings.TrimPrefix(token, "Bearer ")
}
// 验证Token
claims, err := jwt.ParseToken(token)
if err != nil {
response.Error(r, 1003, "Token无效")
return
}
// 检查是否为管理员Token
userType := claims.UserType
if userType != "admin" {
response.Error(r, 1004, "需要管理员权限")
return
}
// 获取管理员ID
adminId := int(claims.UserID)
if adminId <= 0 {
response.Error(r, 1003, "Token无效")
return
}
// 将管理员ID存储到上下文中
r.SetCtxVar("admin_id", adminId)
r.Middleware.Next()
}
// CheckPermissionCode 检查权限编码中间件
func CheckPermissionCode(permissionCode string) func(r *ghttp.Request) {
return func(r *ghttp.Request) {
// 获取用户ID
userId := r.GetCtxVar("user_id")
if userId == nil {
response.Error(r, 1002, "请先登录")
return
}
userIdInt := userId.Int()
if userIdInt <= 0 {
response.Error(r, 1002, "用户信息无效")
return
}
// 检查权限
hasPermission, err := auth.Permission.CheckUserPermission(r.Context(), userIdInt, permissionCode)
if err != nil {
g.Log().Errorf(r.Context(), "权限检查失败: %v", err)
response.Error(r, 1004, "权限检查失败")
return
}
if !hasPermission {
response.Error(r, 1004, "没有访问权限")
return
}
r.Middleware.Next()
}
}
// SuperAdminMiddleware 超级管理员权限验证中间件
func SuperAdminMiddleware(r *ghttp.Request) {
// 获取Token
token := r.Header.Get("Authorization")
if token == "" {
response.Error(r, 1002, "请先登录")
return
}
// 移除Bearer前缀
if strings.HasPrefix(token, "Bearer ") {
token = strings.TrimPrefix(token, "Bearer ")
}
// 验证Token
claims, err := jwt.ParseToken(token)
if err != nil {
response.Error(r, 1003, "Token无效")
return
}
// 检查是否为超级管理员
role := claims.UserType
if role != "super_admin" {
response.Error(r, 1004, "需要超级管理员权限")
return
}
r.Middleware.Next()
}

View File

@@ -0,0 +1,60 @@
package middleware
import (
"fmt"
"nl-video-api/utility/response"
"time"
"github.com/gogf/gf/v2/database/gredis"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// RateLimit 限流中间件
func RateLimit(maxRequests int, window time.Duration) func(r *ghttp.Request) {
return func(r *ghttp.Request) {
var (
ctx = r.Context()
client = g.Redis()
key = fmt.Sprintf("rate_limit:%s", r.GetClientIp())
)
// 获取当前请求次数
count, err := client.Get(ctx, key)
if err != nil {
g.Log().Error(ctx, "Redis获取失败:", err)
r.Middleware.Next()
return
}
// 检查是否超过限制
if count.Int() >= maxRequests {
response.Error(r, response.CodeError, "请求过于频繁,请稍后再试")
return
}
// 增加计数
if count.Int() == 0 {
// 第一次请求,设置过期时间
seconds := int64(window.Seconds())
client.Set(ctx, key, 1, gredis.SetOption{
TTLOption: gredis.TTLOption{EX: &seconds},
})
} else {
// 增加计数
client.Incr(ctx, key)
}
r.Middleware.Next()
}
}
// APIRateLimit API接口限流每分钟60次
func APIRateLimit(r *ghttp.Request) {
RateLimit(60, time.Minute)(r)
}
// LoginRateLimit 登录接口限流每分钟5次
func LoginRateLimit(r *ghttp.Request) {
RateLimit(5, time.Minute)(r)
}

View File

@@ -0,0 +1,160 @@
package middleware
import (
"context"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gconv"
"nl-video-api/utility/logger"
)
// RequestLogger 请求日志中间件
func RequestLogger(r *ghttp.Request) {
// 记录请求开始时间
startTime := time.Now()
// 获取请求信息
method := r.Method
uri := r.RequestURI
ip := r.GetClientIp()
userAgent := r.Header.Get("User-Agent")
// 读取请求体
var requestBody []byte
if r.GetBodyString() != "" {
requestBody = []byte(r.GetBodyString())
}
// 记录请求开始日志
logger.LogInfo(r.Context(), "请求开始 | Method: %s | URI: %s | IP: %s | UserAgent: %s | Body: %s",
method, uri, ip, userAgent, string(requestBody))
// 继续处理请求
r.Middleware.Next()
// 计算请求处理时间
duration := time.Since(startTime)
// 获取响应状态码
status := r.Response.Status
// 获取响应内容(简化处理)
responseBody := ""
// 记录请求完成日志
logger.LogInfo(r.Context(), "请求完成 | Method: %s | URI: %s | IP: %s | Status: %d | Duration: %v | Response: %s",
method, uri, ip, status, duration, responseBody)
// 如果是错误状态码,记录错误日志
if status >= 400 {
logger.LogError(r.Context(), "请求错误 | Method: %s | URI: %s | IP: %s | Status: %d | Duration: %v | Response: %s",
method, uri, ip, status, duration, responseBody)
}
}
// ErrorLogger 错误日志中间件
func ErrorLogger(r *ghttp.Request) {
// 使用defer捕获panic
defer func() {
if err := recover(); err != nil {
// 记录panic错误
logger.LogPanic(r.Context(), "请求panic | Method: %s | URI: %s | IP: %s | Error: %v",
r.Method, r.RequestURI, r.GetClientIp(), err)
// 返回统一错误响应
r.Response.WriteJsonExit(g.Map{
"code": 5000,
"msg": "服务器内部错误",
"result": nil,
})
}
}()
// 继续处理请求
r.Middleware.Next()
}
// BusinessLogger 业务日志记录器
func LogBusinessOperation(ctx context.Context, module string, operation string, userId interface{}, params interface{}, result interface{}, err error) {
fields := g.Map{
"module": module,
"operation": operation,
"user_id": userId,
"params": gconv.String(params),
"result": gconv.String(result),
}
if err != nil {
fields["error"] = err.Error()
logger.LogWithFields(ctx, "error", "error", "业务操作失败", fields)
} else {
logger.LogWithFields(ctx, "log", "info", "业务操作成功", fields)
}
}
// AuthLogger 认证日志记录器
func LogAuthOperation(ctx context.Context, operation string, username string, ip string, userAgent string, success bool, err error) {
fields := g.Map{
"operation": operation,
"username": username,
"ip": ip,
"user_agent": userAgent,
"success": success,
}
if err != nil {
fields["error"] = err.Error()
logger.LogWithFields(ctx, "error", "error", "认证操作失败", fields)
} else {
logger.LogWithFields(ctx, "log", "info", "认证操作成功", fields)
}
}
// APILogger API调用日志记录器
func LogAPICall(ctx context.Context, api string, method string, params interface{}, response interface{}, duration time.Duration, err error) {
fields := g.Map{
"api": api,
"method": method,
"params": gconv.String(params),
"response": gconv.String(response),
"duration": duration.String(),
}
if err != nil {
fields["error"] = err.Error()
logger.LogWithFields(ctx, "error", "error", "API调用失败", fields)
} else {
logger.LogWithFields(ctx, "log", "info", "API调用成功", fields)
}
}
// ValidationLogger 参数验证日志记录器
func LogValidationError(ctx context.Context, field string, value interface{}, rule string, message string) {
fields := g.Map{
"field": field,
"value": gconv.String(value),
"rule": rule,
"message": message,
}
logger.LogWithFields(ctx, "error", "warn", "参数验证失败", fields)
}
// PerformanceLogger 性能日志记录器
func LogPerformance(ctx context.Context, operation string, duration time.Duration, threshold time.Duration) {
fields := g.Map{
"operation": operation,
"duration": duration.String(),
"threshold": threshold.String(),
"slow": duration > threshold,
}
if duration > threshold {
logger.LogWithFields(ctx, "error", "warn", "慢操作检测", fields)
} else {
logger.LogWithFields(ctx, "log", "debug", "性能监控", fields)
}
}

View File

@@ -0,0 +1,74 @@
package middleware
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/utility/response"
)
// ResponseHandler 全局响应处理中间件
// 确保所有响应都返回HTTP 200状态码错误信息通过code和message字段传递
func ResponseHandler(r *ghttp.Request) {
// 设置默认响应头
r.Response.Header().Set("Content-Type", "application/json")
// 继续执行后续中间件和处理函数
r.Middleware.Next()
// 检查响应状态码如果不是200则转换为统一格式
if r.Response.Status != 200 {
// 获取原始状态码
originalStatus := r.Response.Status
// 根据HTTP状态码映射到业务错误码
var businessCode int
var message string
switch originalStatus {
case 400:
businessCode = response.CodeInvalidParam
message = "请求参数错误"
case 401:
businessCode = response.CodeUnauthorized
message = "未授权访问"
case 403:
businessCode = response.CodeForbidden
message = "权限不足"
case 404:
businessCode = response.CodeNotFound
message = "资源不存在"
case 500:
businessCode = response.CodeServerError
message = "服务器内部错误"
default:
businessCode = response.CodeError
message = "请求处理失败"
}
// 清空原有响应内容
r.Response.ClearBuffer()
// 返回统一格式的错误响应HTTP状态码为200
response.Error(r, businessCode, message)
}
}
// ErrorHandler 错误处理中间件
// 捕获panic和其他未处理的错误统一返回格式
func ErrorHandler(r *ghttp.Request) {
defer func() {
if err := recover(); err != nil {
// 记录错误日志
g.Log().Errorf(r.Context(), "Panic recovered: %v", err)
// 清空响应缓冲区
r.Response.ClearBuffer()
// 返回统一格式的错误响应
response.Error(r, response.CodeServerError, "系统内部错误")
}
}()
// 继续执行后续中间件和处理函数
r.Middleware.Next()
}

42
api/v1/admin.go Normal file
View File

@@ -0,0 +1,42 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// AdminGroup 管理员路由组
func AdminGroup(group *ghttp.RouterGroup) {
// 管理员评论管理路由
// AdminCommentRoutes(group) // TODO: 待实现
// 管理员轮播图管理路由
BannerAdminRoutes(group)
// 管理员支付订单管理路由
PaymentOrderAdminRoutes(group)
// VIP等级管理路由
VipLevelAdminRoutes(group)
// 附件管理路由
AttachmentAdminRoutes(group)
// 系统配置管理路由
ConfigAdminRoutes(group)
// 日志管理路由
LogAdminRoutes(group)
// 用户收藏管理路由
// UserCollectAdminRoutes(group) // TODO: 待实现
// 用户观看历史管理路由
// UserWatchHistoryAdminRoutes(group) // TODO: 待实现
}
// AdminAuthMiddleware 管理员认证中间件
func AdminAuthMiddleware(r *ghttp.Request) {
// 这里应该实现管理员认证逻辑
// 暂时跳过,后续实现
r.Middleware.Next()
}

301
api/v1/attachment.go Normal file
View File

@@ -0,0 +1,301 @@
package v1
// 附件管理相关请求和响应结构
// AttachmentUploadReq 上传附件请求
type AttachmentUploadReq struct {
Type string `json:"type" v:"required|in:image,video,audio,document#附件类型不能为空|附件类型只能为image,video,audio,document"`
Category string `json:"category" v:"required|length:1,50#分类不能为空|分类长度为1-50个字符"`
Description string `json:"description" v:"max:200#描述长度不能超过200个字符"`
}
// AttachmentUploadRes 上传附件响应
type AttachmentUploadRes struct {
Id uint `json:"id"`
Filename string `json:"filename"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
}
// AttachmentListReq 获取附件列表请求
type AttachmentListReq struct {
Page int `json:"page" v:"min:1#页码必须大于0"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100"`
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
Category string `json:"category" v:"max:50#分类长度不能超过50个字符"`
Keyword string `json:"keyword" v:"max:50#关键词长度不能超过50个字符"`
StartDate string `json:"start_date" v:"date#开始日期格式不正确"`
EndDate string `json:"end_date" v:"date#结束日期格式不正确"`
MinSize int64 `json:"min_size" v:"min:0#最小文件大小不能小于0"`
MaxSize int64 `json:"max_size" v:"min:0#最大文件大小不能小于0"`
UserId uint `json:"user_id" v:"min:0#用户ID不能小于0"`
}
// AttachmentListRes 获取附件列表响应
type AttachmentListRes struct {
List []AttachmentItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
// AttachmentItem 附件列表项
type AttachmentItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Description string `json:"description"`
UserId uint `json:"user_id"`
Username string `json:"username"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// AttachmentDetailReq 获取附件详情请求
type AttachmentDetailReq struct {
Id uint `json:"id" v:"required|min:1#附件ID不能为空"`
}
// AttachmentDetailRes 获取附件详情响应
type AttachmentDetailRes struct {
Attachment AttachmentDetail `json:"attachment"`
}
// AttachmentDetail 附件详情
type AttachmentDetail struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Description string `json:"description"`
UserId uint `json:"user_id"`
Username string `json:"username"`
DownloadCount int `json:"download_count"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// AttachmentUpdateReq 更新附件请求
type AttachmentUpdateReq struct {
Id uint `json:"id" v:"required|min:1#附件ID不能为空"`
Category string `json:"category" v:"required|length:1,50#分类不能为空|分类长度为1-50个字符"`
Description string `json:"description" v:"max:200#描述长度不能超过200个字符"`
}
// AttachmentDeleteReq 删除附件请求
type AttachmentDeleteReq struct {
Id uint `json:"id" v:"required|min:1#附件ID不能为空"`
}
// AttachmentBatchDeleteReq 批量删除附件请求
type AttachmentBatchDeleteReq struct {
Ids []uint `json:"ids" v:"required|min:1#附件ID列表不能为空"`
}
// AttachmentDownloadReq 下载附件请求
type AttachmentDownloadReq struct {
Id uint `json:"id" v:"required|min:1#附件ID不能为空"`
}
// AttachmentDownloadRes 下载附件响应
type AttachmentDownloadRes struct {
Url string `json:"url"`
Filename string `json:"filename"`
}
// AttachmentCategoryListReq 获取附件分类列表请求
type AttachmentCategoryListReq struct {
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
}
// AttachmentCategoryListRes 获取附件分类列表响应
type AttachmentCategoryListRes struct {
Categories []AttachmentCategoryItem `json:"categories"`
}
// AttachmentCategoryItem 附件分类项
type AttachmentCategoryItem struct {
Category string `json:"category"`
Count int `json:"count"`
}
// AttachmentStatisticsReq 获取附件统计请求
type AttachmentStatisticsReq struct {
StartDate string `json:"start_date" v:"date#开始日期格式不正确"`
EndDate string `json:"end_date" v:"date#结束日期格式不正确"`
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
}
// AttachmentStatisticsRes 获取附件统计响应
type AttachmentStatisticsRes struct {
TotalCount int `json:"total_count"` // 总附件数
TotalSize int64 `json:"total_size"` // 总文件大小
TypeStats []AttachmentTypeStatItem `json:"type_stats"` // 类型统计
CategoryStats []AttachmentCategoryStatItem `json:"category_stats"` // 分类统计
UploadChart []AttachmentUploadChartItem `json:"upload_chart"` // 上传图表数据
SizeChart []AttachmentSizeChartItem `json:"size_chart"` // 大小图表数据
PopularFiles []AttachmentPopularItem `json:"popular_files"` // 热门文件
RecentUploads []AttachmentRecentItem `json:"recent_uploads"` // 最近上传
}
// AttachmentTypeStatItem 附件类型统计项
type AttachmentTypeStatItem struct {
Type string `json:"type"`
Count int `json:"count"`
Size int64 `json:"size"`
Percentage string `json:"percentage"`
}
// AttachmentCategoryStatItem 附件分类统计项
type AttachmentCategoryStatItem struct {
Category string `json:"category"`
Count int `json:"count"`
Size int64 `json:"size"`
Percentage string `json:"percentage"`
}
// AttachmentUploadChartItem 附件上传图表项
type AttachmentUploadChartItem struct {
Date string `json:"date"`
Count int `json:"count"`
Size int64 `json:"size"`
}
// AttachmentSizeChartItem 附件大小图表项
type AttachmentSizeChartItem struct {
SizeRange string `json:"size_range"` // 大小范围,如 "0-1MB", "1-10MB"
Count int `json:"count"`
}
// AttachmentPopularItem 热门附件项
type AttachmentPopularItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
Type string `json:"type"`
Size int64 `json:"size"`
DownloadCount int `json:"download_count"`
CreatedAt string `json:"created_at"`
}
// AttachmentRecentItem 最近上传附件项
type AttachmentRecentItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Type string `json:"type"`
Size int64 `json:"size"`
UserId uint `json:"user_id"`
Username string `json:"username"`
CreatedAt string `json:"created_at"`
}
// AttachmentCleanupReq 清理附件请求
type AttachmentCleanupReq struct {
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
Days int `json:"days" v:"min:1#天数必须大于0"`
MinSize int64 `json:"min_size" v:"min:0#最小文件大小不能小于0"`
MaxSize int64 `json:"max_size" v:"min:0#最大文件大小不能小于0"`
Unused bool `json:"unused"` // 是否只清理未使用的附件
DryRun bool `json:"dry_run"` // 是否只是预览,不实际删除
}
// AttachmentCleanupRes 清理附件响应
type AttachmentCleanupRes struct {
DeletedCount int `json:"deleted_count"` // 删除数量
DeletedSize int64 `json:"deleted_size"` // 删除大小
DeletedFiles []string `json:"deleted_files"` // 删除的文件列表
}
// AttachmentMoveReq 移动附件请求
type AttachmentMoveReq struct {
Ids []uint `json:"ids" v:"required|min:1#附件ID列表不能为空"`
NewCategory string `json:"new_category" v:"required|length:1,50#新分类不能为空|新分类长度为1-50个字符"`
}
// AttachmentCopyReq 复制附件请求
type AttachmentCopyReq struct {
Id uint `json:"id" v:"required|min:1#附件ID不能为空"`
NewCategory string `json:"new_category" v:"length:1,50#新分类长度为1-50个字符"`
Description string `json:"description" v:"max:200#描述长度不能超过200个字符"`
}
// AttachmentCopyRes 复制附件响应
type AttachmentCopyRes struct {
Id uint `json:"id"`
Filename string `json:"filename"`
Url string `json:"url"`
}
// AttachmentRenameReq 重命名附件请求
type AttachmentRenameReq struct {
Id uint `json:"id" v:"required|min:1#附件ID不能为空"`
Filename string `json:"filename" v:"required|length:1,100#文件名不能为空|文件名长度为1-100个字符"`
}
// AttachmentSearchReq 搜索附件请求
type AttachmentSearchReq struct {
Query string `json:"query" v:"required|length:1,100#搜索关键词不能为空|搜索关键词长度为1-100个字符"`
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
Category string `json:"category" v:"max:50#分类长度不能超过50个字符"`
Page int `json:"page" v:"min:1#页码必须大于0"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100"`
}
// AttachmentSearchRes 搜索附件响应
type AttachmentSearchRes struct {
List []AttachmentItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
// AttachmentExportReq 导出附件请求
type AttachmentExportReq struct {
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
Category string `json:"category" v:"max:50#分类长度不能超过50个字符"`
StartDate string `json:"start_date" v:"date#开始日期格式不正确"`
EndDate string `json:"end_date" v:"date#结束日期格式不正确"`
}
// AttachmentExportRes 导出附件响应
type AttachmentExportRes struct {
FileUrl string `json:"file_url"` // 导出文件URL
}
// AttachmentUserListReq 获取用户附件列表请求(用户端)
type AttachmentUserListReq struct {
Page int `json:"page" v:"min:1#页码必须大于0"`
Size int `json:"size" v:"min:1|max:50#每页数量必须大于0|每页数量不能超过50"`
Type string `json:"type" v:"in:,image,video,audio,document#附件类型只能为image,video,audio,document"`
Category string `json:"category" v:"max:50#分类长度不能超过50个字符"`
Keyword string `json:"keyword" v:"max:50#关键词长度不能超过50个字符"`
}
// AttachmentUserListRes 获取用户附件列表响应(用户端)
type AttachmentUserListRes struct {
List []AttachmentUserItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
// AttachmentUserItem 用户附件列表项
type AttachmentUserItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Description string `json:"description"`
CreatedAt string `json:"created_at"`
}

View File

@@ -0,0 +1,19 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// AttachmentUserRoutes 用户附件管理路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func AttachmentUserRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}
// AttachmentAdminRoutes 管理员附件管理路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func AttachmentAdminRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}

43
api/v1/auth.go Normal file
View File

@@ -0,0 +1,43 @@
package v1
import (
"nl-video-api/api/middleware"
"nl-video-api/internal/controller/auth"
"github.com/gogf/gf/v2/net/ghttp"
)
// AuthGroup 认证路由组
func AuthGroup(group *ghttp.RouterGroup) {
// 用户认证相关路由 (无需认证)
group.Group("/auth", func(group *ghttp.RouterGroup) {
// 应用CORS中间件
group.Middleware(middleware.CORS)
// 用户登录
group.POST("/login", auth.Auth.Login)
// 用户注册
group.POST("/register", auth.Auth.Register)
})
// 用户认证后的路由 (需要认证)
group.Group("/auth", func(group *ghttp.RouterGroup) {
// 应用中间件
group.Middleware(middleware.CORS)
group.Middleware(middleware.Auth) // 用户认证中间件
group.Middleware(middleware.RequestLog)
// 获取用户信息
group.GET("/profile", auth.Auth.Profile)
// 更新用户信息
group.POST("/profile", auth.Auth.UpdateProfile)
// 用户登出
group.POST("/logout", auth.Auth.Logout)
// 刷新Token
group.POST("/refresh", auth.Auth.RefreshToken)
})
}

172
api/v1/banner.go Normal file
View File

@@ -0,0 +1,172 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
// BannerListReq 轮播图列表请求
type BannerListReq struct {
g.Meta `path:"/banner/list" method:"get" summary:"轮播图列表" tags:"轮播图管理"`
Position int `json:"position" v:"min:0#位置必须大于等于0" dc:"位置(0:全部,1:首页,2:分类页,3:详情页)" default:"0"`
Status int `json:"status" v:"in:-1,0,1#状态值错误" dc:"状态(-1:全部,0:禁用,1:启用)" default:"-1"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// BannerListRes 轮播图列表响应
type BannerListRes struct {
g.Meta `mime:"application/json"`
List []BannerItem `json:"list" dc:"轮播图列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// BannerItem 轮播图项目
type BannerItem struct {
Id uint `json:"id" dc:"轮播图ID"`
Title string `json:"title" dc:"标题"`
Image string `json:"image" dc:"图片地址"`
Link string `json:"link" dc:"链接地址"`
Position int `json:"position" dc:"位置"`
Sort int `json:"sort" dc:"排序"`
Status int `json:"status" dc:"状态"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
ClickCount int `json:"click_count" dc:"点击次数"`
Description string `json:"description" dc:"描述"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// AdminBannerCreateReq 管理员创建轮播图请求
type AdminBannerCreateReq struct {
g.Meta `path:"/admin/banner/create" method:"post" summary:"创建轮播图" tags:"轮播图管理"`
Title string `json:"title" v:"required|length:1,100#标题不能为空|标题长度为1-100字符" dc:"标题"`
Image string `json:"image" v:"required|url#图片地址不能为空|图片地址格式错误" dc:"图片地址"`
Link string `json:"link" v:"url#链接地址格式错误" dc:"链接地址"`
Position int `json:"position" v:"required|in:1,2,3#位置不能为空|位置值错误" dc:"位置(1:首页,2:分类页,3:详情页)"`
Sort int `json:"sort" v:"min:0#排序必须大于等于0" dc:"排序" default:"0"`
Status int `json:"status" v:"in:0,1#状态值错误" dc:"状态(0:禁用,1:启用)" default:"1"`
StartTime string `json:"start_time" v:"datetime#开始时间格式错误" dc:"开始时间"`
EndTime string `json:"end_time" v:"datetime#结束时间格式错误" dc:"结束时间"`
Description string `json:"description" v:"length:0,500#描述长度不能超过500字符" dc:"描述"`
}
// AdminBannerCreateRes 管理员创建轮播图响应
type AdminBannerCreateRes struct {
g.Meta `mime:"application/json"`
Id uint `json:"id" dc:"轮播图ID"`
}
// AdminBannerUpdateReq 管理员更新轮播图请求
type AdminBannerUpdateReq struct {
g.Meta `path:"/admin/banner/update" method:"post" summary:"更新轮播图" tags:"轮播图管理"`
Id uint `json:"id" v:"required|min:1#轮播图ID不能为空|轮播图ID必须大于0" dc:"轮播图ID"`
Title string `json:"title" v:"required|length:1,100#标题不能为空|标题长度为1-100字符" dc:"标题"`
Image string `json:"image" v:"required|url#图片地址不能为空|图片地址格式错误" dc:"图片地址"`
Link string `json:"link" v:"url#链接地址格式错误" dc:"链接地址"`
Position int `json:"position" v:"required|in:1,2,3#位置不能为空|位置值错误" dc:"位置(1:首页,2:分类页,3:详情页)"`
Sort int `json:"sort" v:"min:0#排序必须大于等于0" dc:"排序"`
Status int `json:"status" v:"in:0,1#状态值错误" dc:"状态(0:禁用,1:启用)"`
StartTime string `json:"start_time" v:"datetime#开始时间格式错误" dc:"开始时间"`
EndTime string `json:"end_time" v:"datetime#结束时间格式错误" dc:"结束时间"`
Description string `json:"description" v:"length:0,500#描述长度不能超过500字符" dc:"描述"`
}
// AdminBannerUpdateRes 管理员更新轮播图响应
type AdminBannerUpdateRes struct {
g.Meta `mime:"application/json"`
}
// AdminBannerDeleteReq 管理员删除轮播图请求
type AdminBannerDeleteReq struct {
g.Meta `path:"/admin/banner/delete" method:"post" summary:"删除轮播图" tags:"轮播图管理"`
Id uint `json:"id" v:"required|min:1#轮播图ID不能为空|轮播图ID必须大于0" dc:"轮播图ID"`
}
// AdminBannerDeleteRes 管理员删除轮播图响应
type AdminBannerDeleteRes struct {
g.Meta `mime:"application/json"`
}
// AdminBannerDetailReq 管理员轮播图详情请求
type AdminBannerDetailReq struct {
g.Meta `path:"/admin/banner/detail" method:"get" summary:"轮播图详情" tags:"轮播图管理"`
Id uint `json:"id" v:"required|min:1#轮播图ID不能为空|轮播图ID必须大于0" dc:"轮播图ID"`
}
// AdminBannerDetailRes 管理员轮播图详情响应
type AdminBannerDetailRes struct {
g.Meta `mime:"application/json"`
Banner BannerItem `json:"banner" dc:"轮播图详情"`
}
// AdminBannerListReq 管理员轮播图列表请求
type AdminBannerListReq struct {
g.Meta `path:"/admin/banner/list" method:"get" summary:"管理员轮播图列表" tags:"轮播图管理"`
Position int `json:"position" v:"min:0#位置必须大于等于0" dc:"位置(0:全部,1:首页,2:分类页,3:详情页)" default:"0"`
Status int `json:"status" v:"in:-1,0,1#状态值错误" dc:"状态(-1:全部,0:禁用,1:启用)" default:"-1"`
Keyword string `json:"keyword" dc:"关键词搜索"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// AdminBannerListRes 管理员轮播图列表响应
type AdminBannerListRes struct {
g.Meta `mime:"application/json"`
List []AdminBannerItem `json:"list" dc:"轮播图列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// AdminBannerItem 管理员轮播图项目
type AdminBannerItem struct {
Id uint `json:"id" dc:"轮播图ID"`
Title string `json:"title" dc:"标题"`
Image string `json:"image" dc:"图片地址"`
Link string `json:"link" dc:"链接地址"`
Position int `json:"position" dc:"位置"`
Sort int `json:"sort" dc:"排序"`
Status int `json:"status" dc:"状态"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
ClickCount int `json:"click_count" dc:"点击次数"`
Description string `json:"description" dc:"描述"`
CreatedAt string `json:"created_at" dc:"创建时间"`
UpdatedAt string `json:"updated_at" dc:"更新时间"`
}
// AdminBannerUpdateStatusReq 管理员更新轮播图状态请求
type AdminBannerUpdateStatusReq struct {
g.Meta `path:"/admin/banner/status" method:"post" summary:"更新轮播图状态" tags:"轮播图管理"`
Id uint `json:"id" v:"required|min:1#轮播图ID不能为空|轮播图ID必须大于0" dc:"轮播图ID"`
Status int `json:"status" v:"required|in:0,1#状态不能为空|状态值错误" dc:"状态(0:禁用,1:启用)"`
}
// AdminBannerUpdateStatusRes 管理员更新轮播图状态响应
type AdminBannerUpdateStatusRes struct {
g.Meta `mime:"application/json"`
}
// AdminBannerBatchDeleteReq 管理员批量删除轮播图请求
type AdminBannerBatchDeleteReq struct {
g.Meta `path:"/admin/banner/batch-delete" method:"post" summary:"批量删除轮播图" tags:"轮播图管理"`
Ids []uint `json:"ids" v:"required|length:1,100#轮播图ID列表不能为空|最多选择100条记录" dc:"轮播图ID列表"`
}
// AdminBannerBatchDeleteRes 管理员批量删除轮播图响应
type AdminBannerBatchDeleteRes struct {
g.Meta `mime:"application/json"`
}
// BannerClickReq 轮播图点击请求
type BannerClickReq struct {
g.Meta `path:"/banner/click" method:"post" summary:"轮播图点击" tags:"轮播图管理"`
Id uint `json:"id" v:"required|min:1#轮播图ID不能为空|轮播图ID必须大于0" dc:"轮播图ID"`
}
// BannerClickRes 轮播图点击响应
type BannerClickRes struct {
g.Meta `mime:"application/json"`
}

19
api/v1/banner_routes.go Normal file
View File

@@ -0,0 +1,19 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// BannerUserRoutes 用户轮播图路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func BannerUserRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}
// BannerAdminRoutes 管理员轮播图路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func BannerAdminRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}

156
api/v1/comment.go Normal file
View File

@@ -0,0 +1,156 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
// CommentAddReq 添加评论请求
type CommentAddReq struct {
g.Meta `path:"/comment/add" method:"post" summary:"添加评论" tags:"评论管理"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
ParentId int `json:"parent_id" v:"min:0#父评论ID必须大于等于0" dc:"父评论ID" default:"0"`
Content string `json:"content" v:"required|length:1,500#评论内容不能为空|评论内容长度为1-500字符" dc:"评论内容"`
}
// CommentAddRes 添加评论响应
type CommentAddRes struct {
g.Meta `mime:"application/json"`
Id uint `json:"id" dc:"评论ID"`
}
// CommentListReq 评论列表请求
type CommentListReq struct {
g.Meta `path:"/comment/list" method:"get" summary:"评论列表" tags:"评论管理"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
ParentId int `json:"parent_id" v:"min:0#父评论ID必须大于等于0" dc:"父评论ID" default:"0"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// CommentListRes 评论列表响应
type CommentListRes struct {
g.Meta `mime:"application/json"`
List []CommentItem `json:"list" dc:"评论列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// CommentItem 评论项目
type CommentItem struct {
Id uint `json:"id" dc:"评论ID"`
UserId int `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
UserAvatar string `json:"user_avatar" dc:"用户头像"`
MovieId int `json:"movie_id" dc:"影片ID"`
ParentId int `json:"parent_id" dc:"父评论ID"`
Content string `json:"content" dc:"评论内容"`
LikeCount int `json:"like_count" dc:"点赞数"`
IsLiked bool `json:"is_liked" dc:"是否已点赞"`
Status int `json:"status" dc:"状态"`
CreatedAt string `json:"created_at" dc:"创建时间"`
Replies []CommentItem `json:"replies,omitempty" dc:"回复列表"`
}
// CommentDeleteReq 删除评论请求
type CommentDeleteReq struct {
g.Meta `path:"/comment/delete" method:"post" summary:"删除评论" tags:"评论管理"`
Id uint `json:"id" v:"required|min:1#评论ID不能为空|评论ID必须大于0" dc:"评论ID"`
}
// CommentDeleteRes 删除评论响应
type CommentDeleteRes struct {
g.Meta `mime:"application/json"`
}
// CommentLikeReq 点赞评论请求
type CommentLikeReq struct {
g.Meta `path:"/comment/like" method:"post" summary:"点赞评论" tags:"评论管理"`
Id uint `json:"id" v:"required|min:1#评论ID不能为空|评论ID必须大于0" dc:"评论ID"`
}
// CommentLikeRes 点赞评论响应
type CommentLikeRes struct {
g.Meta `mime:"application/json"`
}
// CommentUnlikeReq 取消点赞请求
type CommentUnlikeReq struct {
g.Meta `path:"/comment/unlike" method:"post" summary:"取消点赞" tags:"评论管理"`
Id uint `json:"id" v:"required|min:1#评论ID不能为空|评论ID必须大于0" dc:"评论ID"`
}
// CommentUnlikeRes 取消点赞响应
type CommentUnlikeRes struct {
g.Meta `mime:"application/json"`
}
// CommentReportReq 举报评论请求
type CommentReportReq struct {
g.Meta `path:"/comment/report" method:"post" summary:"举报评论" tags:"评论管理"`
Id uint `json:"id" v:"required|min:1#评论ID不能为空|评论ID必须大于0" dc:"评论ID"`
Reason string `json:"reason" v:"required|length:1,200#举报原因不能为空|举报原因长度为1-200字符" dc:"举报原因"`
}
// CommentReportRes 举报评论响应
type CommentReportRes struct {
g.Meta `mime:"application/json"`
}
// AdminCommentListReq 管理员评论列表请求
type AdminCommentListReq struct {
g.Meta `path:"/admin/comment/list" method:"get" summary:"管理员评论列表" tags:"评论管理"`
MovieId int `json:"movie_id" v:"min:0#影片ID必须大于等于0" dc:"影片ID"`
UserId int `json:"user_id" v:"min:0#用户ID必须大于等于0" dc:"用户ID"`
Status int `json:"status" v:"in:-1,0,1,2#状态值错误" dc:"状态(-1:全部,0:待审核,1:已通过,2:已拒绝)" default:"-1"`
Keyword string `json:"keyword" dc:"关键词搜索"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// AdminCommentListRes 管理员评论列表响应
type AdminCommentListRes struct {
g.Meta `mime:"application/json"`
List []AdminCommentItem `json:"list" dc:"评论列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// AdminCommentItem 管理员评论项目
type AdminCommentItem struct {
Id uint `json:"id" dc:"评论ID"`
UserId int `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
MovieId int `json:"movie_id" dc:"影片ID"`
MovieName string `json:"movie_name" dc:"影片名称"`
ParentId int `json:"parent_id" dc:"父评论ID"`
Content string `json:"content" dc:"评论内容"`
LikeCount int `json:"like_count" dc:"点赞数"`
Status int `json:"status" dc:"状态"`
CreatedAt string `json:"created_at" dc:"创建时间"`
UpdatedAt string `json:"updated_at" dc:"更新时间"`
}
// AdminCommentUpdateStatusReq 管理员更新评论状态请求
type AdminCommentUpdateStatusReq struct {
g.Meta `path:"/admin/comment/status" method:"post" summary:"更新评论状态" tags:"评论管理"`
Id uint `json:"id" v:"required|min:1#评论ID不能为空|评论ID必须大于0" dc:"评论ID"`
Status int `json:"status" v:"required|in:0,1,2#状态不能为空|状态值错误" dc:"状态(0:待审核,1:已通过,2:已拒绝)"`
}
// AdminCommentUpdateStatusRes 管理员更新评论状态响应
type AdminCommentUpdateStatusRes struct {
g.Meta `mime:"application/json"`
}
// AdminCommentBatchDeleteReq 管理员批量删除评论请求
type AdminCommentBatchDeleteReq struct {
g.Meta `path:"/admin/comment/batch-delete" method:"post" summary:"批量删除评论" tags:"评论管理"`
Ids []uint `json:"ids" v:"required|length:1,100#评论ID列表不能为空|最多选择100条记录" dc:"评论ID列表"`
}
// AdminCommentBatchDeleteRes 管理员批量删除评论响应
type AdminCommentBatchDeleteRes struct {
g.Meta `mime:"application/json"`
}

28
api/v1/comment_routes.go Normal file
View File

@@ -0,0 +1,28 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// CommentUserRoutes 用户评论路由
func CommentUserRoutes(group *ghttp.RouterGroup) {
// TODO: 需要实现middleware和user controller
// group.Middleware(middleware.AuthMiddleware)
// group.POST("/comment/create", middleware.AuthMiddleware, user.Comment.Create)
// group.GET("/comment/list", middleware.AuthMiddleware, user.Comment.GetList)
// 评论点赞
// group.POST("/comment/like", user.Comment.Like)
// 评论举报
// group.POST("/comment/report", user.Comment.Report)
}
// CommentAdminRoutes 管理员评论路由
func CommentAdminRoutes(group *ghttp.RouterGroup) {
// TODO: 需要实现admin controller
// group.GET("/admin/comment/list", admin.Comment.GetList)
// group.POST("/admin/comment/delete", admin.Comment.Delete)
// group.POST("/admin/comment/batch-delete", admin.Comment.BatchDelete)
// group.POST("/admin/comment/update-status", admin.Comment.UpdateStatus)
}

313
api/v1/config.go Normal file
View File

@@ -0,0 +1,313 @@
package v1
import "github.com/gogf/gf/v2/frame/g"
// ===== 系统配置管理相关结构 =====
// ConfigListReq 获取配置列表请求
type ConfigListReq struct {
g.Meta `path:"/config/list" method:"get" summary:"获取配置列表" tags:"系统配置管理"`
Page int `json:"page" dc:"页码默认1"`
Size int `json:"size" dc:"每页数量默认10"`
Group string `json:"group" dc:"配置分组"`
Keyword string `json:"keyword" dc:"搜索关键词"`
Status int `json:"status" dc:"状态0-禁用1-启用"`
}
// ConfigListRes 获取配置列表响应
type ConfigListRes struct {
List []ConfigItem `json:"list" dc:"配置列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页码"`
Size int `json:"size" dc:"每页数量"`
}
// ConfigItem 配置项
type ConfigItem struct {
Id uint `json:"id" dc:"配置ID"`
Name string `json:"name" dc:"配置名称"`
Key string `json:"key" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
Group string `json:"group" dc:"配置分组"`
Type string `json:"type" dc:"配置类型"`
Description string `json:"description" dc:"配置描述"`
Sort int `json:"sort" dc:"排序"`
Status int `json:"status" dc:"状态0-禁用1-启用"`
CreatedAt string `json:"created_at" dc:"创建时间"`
UpdatedAt string `json:"updated_at" dc:"更新时间"`
}
// ConfigDetailReq 获取配置详情请求
type ConfigDetailReq struct {
g.Meta `path:"/config/detail" method:"get" summary:"获取配置详情" tags:"系统配置管理"`
Id uint `json:"id" v:"required|min:1#请输入配置ID|配置ID不能为空" dc:"配置ID"`
}
// ConfigDetailRes 获取配置详情响应
type ConfigDetailRes struct {
Config ConfigDetail `json:"config" dc:"配置详情"`
}
// ConfigDetail 配置详情
type ConfigDetail struct {
Id uint `json:"id" dc:"配置ID"`
Name string `json:"name" dc:"配置名称"`
Key string `json:"key" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
Group string `json:"group" dc:"配置分组"`
Type string `json:"type" dc:"配置类型"`
Description string `json:"description" dc:"配置描述"`
Sort int `json:"sort" dc:"排序"`
Status int `json:"status" dc:"状态0-禁用1-启用"`
CreatedAt string `json:"created_at" dc:"创建时间"`
UpdatedAt string `json:"updated_at" dc:"更新时间"`
}
// ConfigCreateReq 创建配置请求
type ConfigCreateReq struct {
g.Meta `path:"/config/create" method:"post" summary:"创建配置" tags:"系统配置管理"`
Name string `json:"name" v:"required|length:1,100#请输入配置名称|配置名称长度为1-100个字符" dc:"配置名称"`
Key string `json:"key" v:"required|length:1,100#请输入配置键|配置键长度为1-100个字符" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
Group string `json:"group" v:"required|length:1,50#请输入配置分组|配置分组长度为1-50个字符" dc:"配置分组"`
Type string `json:"type" v:"required|in:string,int,float,bool,json#请选择配置类型|配置类型必须为string,int,float,bool,json之一" dc:"配置类型"`
Description string `json:"description" dc:"配置描述"`
Sort int `json:"sort" dc:"排序"`
Status int `json:"status" v:"in:0,1#状态值错误" dc:"状态0-禁用1-启用"`
}
// ConfigUpdateReq 更新配置请求
type ConfigUpdateReq struct {
g.Meta `path:"/config/update" method:"post" summary:"更新配置" tags:"系统配置管理"`
Id uint `json:"id" v:"required|min:1#请输入配置ID|配置ID不能为空" dc:"配置ID"`
Name string `json:"name" v:"required|length:1,100#请输入配置名称|配置名称长度为1-100个字符" dc:"配置名称"`
Value string `json:"value" dc:"配置值"`
Group string `json:"group" v:"required|length:1,50#请输入配置分组|配置分组长度为1-50个字符" dc:"配置分组"`
Type string `json:"type" v:"required|in:string,int,float,bool,json#请选择配置类型|配置类型必须为string,int,float,bool,json之一" dc:"配置类型"`
Description string `json:"description" dc:"配置描述"`
Sort int `json:"sort" dc:"排序"`
Status int `json:"status" v:"in:0,1#状态值错误" dc:"状态0-禁用1-启用"`
}
// ConfigDeleteReq 删除配置请求
type ConfigDeleteReq struct {
g.Meta `path:"/config/delete" method:"post" summary:"删除配置" tags:"系统配置管理"`
Id uint `json:"id" v:"required|min:1#请输入配置ID|配置ID不能为空" dc:"配置ID"`
}
// ConfigBatchDeleteReq 批量删除配置请求
type ConfigBatchDeleteReq struct {
g.Meta `path:"/config/batch-delete" method:"post" summary:"批量删除配置" tags:"系统配置管理"`
Ids []uint `json:"ids" v:"required|length:1,100#请选择要删除的配置|最多选择100个配置" dc:"配置ID列表"`
}
// ConfigGetByKeyReq 根据键获取配置请求
type ConfigGetByKeyReq struct {
g.Meta `path:"/config/get-by-key" method:"get" summary:"根据键获取配置" tags:"系统配置管理"`
Key string `json:"key" v:"required#请输入配置键" dc:"配置键"`
}
// ConfigGetByKeyRes 根据键获取配置响应
type ConfigGetByKeyRes struct {
Value string `json:"value" dc:"配置值"`
}
// ConfigGetByGroupReq 根据分组获取配置请求
type ConfigGetByGroupReq struct {
g.Meta `path:"/config/get-by-group" method:"get" summary:"根据分组获取配置" tags:"系统配置管理"`
Group string `json:"group" v:"required#请输入配置分组" dc:"配置分组"`
}
// ConfigGetByGroupRes 根据分组获取配置响应
type ConfigGetByGroupRes struct {
Configs []ConfigGroupItem `json:"configs" dc:"配置列表"`
}
// ConfigGroupItem 分组配置项
type ConfigGroupItem struct {
Key string `json:"key" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
Name string `json:"name" dc:"配置名称"`
Type string `json:"type" dc:"配置类型"`
Description string `json:"description" dc:"配置描述"`
}
// ConfigSetReq 设置配置请求
type ConfigSetReq struct {
g.Meta `path:"/config/set" method:"post" summary:"设置配置" tags:"系统配置管理"`
Key string `json:"key" v:"required#请输入配置键" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
}
// ConfigBatchSetReq 批量设置配置请求
type ConfigBatchSetReq struct {
g.Meta `path:"/config/batch-set" method:"post" summary:"批量设置配置" tags:"系统配置管理"`
Configs []ConfigSetItem `json:"configs" v:"required|length:1,100#请输入配置列表|最多设置100个配置" dc:"配置列表"`
}
// ConfigSetItem 设置配置项
type ConfigSetItem struct {
Key string `json:"key" v:"required#请输入配置键" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
}
// ConfigGroupListReq 获取配置分组列表请求
type ConfigGroupListReq struct {
g.Meta `path:"/config/group/list" method:"get" summary:"获取配置分组列表" tags:"系统配置管理"`
}
// ConfigGroupListRes 获取配置分组列表响应
type ConfigGroupListRes struct {
Groups []ConfigGroupStatItem `json:"groups" dc:"分组列表"`
}
// ConfigGroupStatItem 配置分组统计项
type ConfigGroupStatItem struct {
Group string `json:"group" dc:"分组名称"`
Count int `json:"count" dc:"配置数量"`
Description string `json:"description" dc:"分组描述"`
}
// ConfigExportReq 导出配置请求
type ConfigExportReq struct {
g.Meta `path:"/config/export" method:"get" summary:"导出配置" tags:"系统配置管理"`
Group string `json:"group" dc:"配置分组,为空则导出全部"`
Format string `json:"format" v:"in:json,yaml,ini#导出格式错误" dc:"导出格式json,yaml,ini"`
}
// ConfigExportRes 导出配置响应
type ConfigExportRes struct {
Content string `json:"content" dc:"导出内容"`
Filename string `json:"filename" dc:"文件名"`
}
// ConfigImportReq 导入配置请求
type ConfigImportReq struct {
g.Meta `path:"/config/import" method:"post" summary:"导入配置" tags:"系统配置管理"`
Content string `json:"content" v:"required#请输入导入内容" dc:"导入内容"`
Format string `json:"format" v:"required|in:json,yaml,ini#请选择导入格式|导入格式必须为json,yaml,ini之一" dc:"导入格式"`
Group string `json:"group" dc:"目标分组,为空则使用原分组"`
Mode string `json:"mode" v:"in:merge,replace#导入模式错误" dc:"导入模式merge-合并replace-替换"`
}
// ConfigImportRes 导入配置响应
type ConfigImportRes struct {
Success int `json:"success" dc:"成功导入数量"`
Failed int `json:"failed" dc:"失败数量"`
Total int `json:"total" dc:"总数量"`
}
// ConfigCacheReq 缓存配置请求
type ConfigCacheReq struct {
g.Meta `path:"/config/cache" method:"post" summary:"缓存配置" tags:"系统配置管理"`
Group string `json:"group" dc:"配置分组,为空则缓存全部"`
}
// ConfigClearCacheReq 清除配置缓存请求
type ConfigClearCacheReq struct {
g.Meta `path:"/config/clear-cache" method:"post" summary:"清除配置缓存" tags:"系统配置管理"`
Group string `json:"group" dc:"配置分组,为空则清除全部"`
}
// ConfigValidateReq 验证配置请求
type ConfigValidateReq struct {
g.Meta `path:"/config/validate" method:"post" summary:"验证配置" tags:"系统配置管理"`
Key string `json:"key" v:"required#请输入配置键" dc:"配置键"`
Value string `json:"value" dc:"配置值"`
Type string `json:"type" v:"required|in:string,int,float,bool,json#请选择配置类型|配置类型必须为string,int,float,bool,json之一" dc:"配置类型"`
}
// ConfigValidateRes 验证配置响应
type ConfigValidateRes struct {
Valid bool `json:"valid" dc:"是否有效"`
Message string `json:"message" dc:"验证消息"`
}
// ConfigBackupReq 备份配置请求
type ConfigBackupReq struct {
g.Meta `path:"/config/backup" method:"post" summary:"备份配置" tags:"系统配置管理"`
Name string `json:"name" v:"required|length:1,100#请输入备份名称|备份名称长度为1-100个字符" dc:"备份名称"`
Group string `json:"group" dc:"配置分组,为空则备份全部"`
}
// ConfigBackupRes 备份配置响应
type ConfigBackupRes struct {
BackupId string `json:"backup_id" dc:"备份ID"`
Filename string `json:"filename" dc:"备份文件名"`
}
// ConfigRestoreReq 恢复配置请求
type ConfigRestoreReq struct {
g.Meta `path:"/config/restore" method:"post" summary:"恢复配置" tags:"系统配置管理"`
BackupId string `json:"backup_id" v:"required#请输入备份ID" dc:"备份ID"`
Mode string `json:"mode" v:"in:merge,replace#恢复模式错误" dc:"恢复模式merge-合并replace-替换"`
}
// ConfigRestoreRes 恢复配置响应
type ConfigRestoreRes struct {
Success int `json:"success" dc:"成功恢复数量"`
Failed int `json:"failed" dc:"失败数量"`
Total int `json:"total" dc:"总数量"`
}
// ConfigHistoryReq 获取配置历史请求
type ConfigHistoryReq struct {
g.Meta `path:"/config/history" method:"get" summary:"获取配置历史" tags:"系统配置管理"`
Key string `json:"key" v:"required#请输入配置键" dc:"配置键"`
Page int `json:"page" dc:"页码默认1"`
Size int `json:"size" dc:"每页数量默认10"`
}
// ConfigHistoryRes 获取配置历史响应
type ConfigHistoryRes struct {
List []ConfigHistoryItem `json:"list" dc:"历史列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页码"`
Size int `json:"size" dc:"每页数量"`
}
// ConfigHistoryItem 配置历史项
type ConfigHistoryItem struct {
Id uint `json:"id" dc:"历史ID"`
Key string `json:"key" dc:"配置键"`
OldValue string `json:"old_value" dc:"旧值"`
NewValue string `json:"new_value" dc:"新值"`
Operation string `json:"operation" dc:"操作类型"`
UserId uint `json:"user_id" dc:"操作用户ID"`
Username string `json:"username" dc:"操作用户名"`
CreatedAt string `json:"created_at" dc:"操作时间"`
}
// ===== 用户端配置相关结构 =====
// ConfigUserGetReq 用户获取配置请求
type ConfigUserGetReq struct {
g.Meta `path:"/config/get" method:"get" summary:"获取配置" tags:"用户配置"`
Key string `json:"key" v:"required#请输入配置键" dc:"配置键"`
}
// ConfigUserGetRes 用户获取配置响应
type ConfigUserGetRes struct {
Value string `json:"value" dc:"配置值"`
}
// ConfigUserGetGroupReq 用户获取分组配置请求
type ConfigUserGetGroupReq struct {
g.Meta `path:"/config/group" method:"get" summary:"获取分组配置" tags:"用户配置"`
Group string `json:"group" v:"required#请输入配置分组" dc:"配置分组"`
}
// ConfigUserGetGroupRes 用户获取分组配置响应
type ConfigUserGetGroupRes struct {
Configs map[string]string `json:"configs" dc:"配置键值对"`
}
// ConfigUserGetPublicReq 用户获取公开配置请求
type ConfigUserGetPublicReq struct {
g.Meta `path:"/config/public" method:"get" summary:"获取公开配置" tags:"用户配置"`
}
// ConfigUserGetPublicRes 用户获取公开配置响应
type ConfigUserGetPublicRes struct {
Configs map[string]interface{} `json:"configs" dc:"公开配置"`
}

19
api/v1/config_routes.go Normal file
View File

@@ -0,0 +1,19 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// ConfigUserRoutes 用户配置路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func ConfigUserRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}
// ConfigAdminRoutes 管理员配置路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func ConfigAdminRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}

473
api/v1/log.go Normal file
View File

@@ -0,0 +1,473 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
// ===== 管理员日志管理 =====
// AdminLogListReq 管理员日志列表请求
type AdminLogListReq struct {
g.Meta `path:"/admin-log/list" method:"get" tags:"管理员日志" summary:"获取管理员日志列表"`
Page int `json:"page" v:"min:1" dc:"页码默认1"`
Size int `json:"size" v:"min:1|max:100" dc:"每页数量默认10"`
AdminId int `json:"admin_id" dc:"管理员ID"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Status int `json:"status" dc:"状态1成功0失败"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Keyword string `json:"keyword" dc:"关键词搜索"`
}
// AdminLogListRes 管理员日志列表响应
type AdminLogListRes struct {
List []AdminLogItem `json:"list" dc:"日志列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// AdminLogItem 管理员日志项
type AdminLogItem struct {
Id int `json:"id" dc:"日志ID"`
AdminId int `json:"admin_id" dc:"管理员ID"`
AdminName string `json:"admin_name" dc:"管理员名称"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Description string `json:"description" dc:"操作描述"`
RequestData string `json:"request_data" dc:"请求数据"`
ResponseData string `json:"response_data" dc:"响应数据"`
Ip string `json:"ip" dc:"IP地址"`
UserAgent string `json:"user_agent" dc:"用户代理"`
Status int `json:"status" dc:"状态1成功0失败"`
ErrorMsg string `json:"error_msg" dc:"错误信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// AdminLogDetailReq 管理员日志详情请求
type AdminLogDetailReq struct {
g.Meta `path:"/admin-log/detail" method:"get" tags:"管理员日志" summary:"获取管理员日志详情"`
Id int `json:"id" v:"required|min:1" dc:"日志ID"`
}
// AdminLogDetailRes 管理员日志详情响应
type AdminLogDetailRes struct {
Log AdminLogDetail `json:"log" dc:"日志详情"`
}
// AdminLogDetail 管理员日志详情
type AdminLogDetail struct {
Id int `json:"id" dc:"日志ID"`
AdminId int `json:"admin_id" dc:"管理员ID"`
AdminName string `json:"admin_name" dc:"管理员名称"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Description string `json:"description" dc:"操作描述"`
RequestData string `json:"request_data" dc:"请求数据"`
ResponseData string `json:"response_data" dc:"响应数据"`
Ip string `json:"ip" dc:"IP地址"`
UserAgent string `json:"user_agent" dc:"用户代理"`
Status int `json:"status" dc:"状态1成功0失败"`
ErrorMsg string `json:"error_msg" dc:"错误信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// AdminLogDeleteReq 删除管理员日志请求
type AdminLogDeleteReq struct {
g.Meta `path:"/admin-log/delete" method:"post" tags:"管理员日志" summary:"删除管理员日志"`
Id int `json:"id" v:"required|min:1" dc:"日志ID"`
}
// AdminLogDeleteRes 删除管理员日志响应
type AdminLogDeleteRes struct {
Message string `json:"message" dc:"操作结果"`
}
// AdminLogBatchDeleteReq 批量删除管理员日志请求
type AdminLogBatchDeleteReq struct {
g.Meta `path:"/admin-log/batch-delete" method:"post" tags:"管理员日志" summary:"批量删除管理员日志"`
Ids []int `json:"ids" v:"required" dc:"日志ID列表"`
}
// AdminLogBatchDeleteRes 批量删除管理员日志响应
type AdminLogBatchDeleteRes struct {
Message string `json:"message" dc:"操作结果"`
}
// AdminLogClearReq 清空管理员日志请求
type AdminLogClearReq struct {
g.Meta `path:"/admin-log/clear" method:"post" tags:"管理员日志" summary:"清空管理员日志"`
Days int `json:"days" dc:"保留天数0表示全部清空"`
AdminId int `json:"admin_id" dc:"管理员ID0表示所有管理员"`
Module string `json:"module" dc:"模块名称,空表示所有模块"`
}
// AdminLogClearRes 清空管理员日志响应
type AdminLogClearRes struct {
Message string `json:"message" dc:"操作结果"`
Count int `json:"count" dc:"清空数量"`
}
// AdminLogExportReq 导出管理员日志请求
type AdminLogExportReq struct {
g.Meta `path:"/admin-log/export" method:"get" tags:"管理员日志" summary:"导出管理员日志"`
AdminId int `json:"admin_id" dc:"管理员ID"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Status int `json:"status" dc:"状态1成功0失败"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Format string `json:"format" dc:"导出格式excel,csv,json"`
}
// AdminLogExportRes 导出管理员日志响应
type AdminLogExportRes struct {
Content string `json:"content" dc:"导出内容"`
Filename string `json:"filename" dc:"文件名"`
}
// AdminLogStatsReq 管理员日志统计请求
type AdminLogStatsReq struct {
g.Meta `path:"/admin-log/stats" method:"get" tags:"管理员日志" summary:"获取管理员日志统计"`
AdminId int `json:"admin_id" dc:"管理员ID"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Type string `json:"type" dc:"统计类型day,week,month"`
}
// AdminLogStatsRes 管理员日志统计响应
type AdminLogStatsRes struct {
Stats AdminLogStatsData `json:"stats" dc:"统计数据"`
}
// AdminLogStatsData 管理员日志统计数据
type AdminLogStatsData struct {
Total int `json:"total" dc:"总数"`
Success int `json:"success" dc:"成功数"`
Failed int `json:"failed" dc:"失败数"`
SuccessRate float64 `json:"success_rate" dc:"成功率"`
ModuleStats []AdminLogModuleStats `json:"module_stats" dc:"模块统计"`
ActionStats []AdminLogActionStats `json:"action_stats" dc:"操作统计"`
TimeStats []AdminLogTimeStats `json:"time_stats" dc:"时间统计"`
AdminStats []AdminLogAdminStats `json:"admin_stats" dc:"管理员统计"`
}
// AdminLogModuleStats 模块统计
type AdminLogModuleStats struct {
Module string `json:"module" dc:"模块名称"`
Count int `json:"count" dc:"数量"`
}
// AdminLogActionStats 操作统计
type AdminLogActionStats struct {
Action string `json:"action" dc:"操作类型"`
Count int `json:"count" dc:"数量"`
}
// AdminLogTimeStats 时间统计
type AdminLogTimeStats struct {
Time string `json:"time" dc:"时间"`
Count int `json:"count" dc:"数量"`
}
// AdminLogAdminStats 管理员统计
type AdminLogAdminStats struct {
AdminId int `json:"admin_id" dc:"管理员ID"`
AdminName string `json:"admin_name" dc:"管理员名称"`
Count int `json:"count" dc:"数量"`
}
// ===== 用户日志管理 =====
// UserLogListReq 用户日志列表请求
type UserLogListReq struct {
g.Meta `path:"/user-log/list" method:"get" tags:"用户日志" summary:"获取用户日志列表"`
Page int `json:"page" v:"min:1" dc:"页码默认1"`
Size int `json:"size" v:"min:1|max:100" dc:"每页数量默认10"`
UserId int `json:"user_id" dc:"用户ID"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Status int `json:"status" dc:"状态1成功0失败"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Keyword string `json:"keyword" dc:"关键词搜索"`
}
// UserLogListRes 用户日志列表响应
type UserLogListRes struct {
List []UserLogItem `json:"list" dc:"日志列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// UserLogItem 用户日志项
type UserLogItem struct {
Id int `json:"id" dc:"日志ID"`
UserId int `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Description string `json:"description" dc:"操作描述"`
RequestData string `json:"request_data" dc:"请求数据"`
ResponseData string `json:"response_data" dc:"响应数据"`
Ip string `json:"ip" dc:"IP地址"`
UserAgent string `json:"user_agent" dc:"用户代理"`
Status int `json:"status" dc:"状态1成功0失败"`
ErrorMsg string `json:"error_msg" dc:"错误信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// UserLogDetailReq 用户日志详情请求
type UserLogDetailReq struct {
g.Meta `path:"/user-log/detail" method:"get" tags:"用户日志" summary:"获取用户日志详情"`
Id int `json:"id" v:"required|min:1" dc:"日志ID"`
}
// UserLogDetailRes 用户日志详情响应
type UserLogDetailRes struct {
Log UserLogDetail `json:"log" dc:"日志详情"`
}
// UserLogDetail 用户日志详情
type UserLogDetail struct {
Id int `json:"id" dc:"日志ID"`
UserId int `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Description string `json:"description" dc:"操作描述"`
RequestData string `json:"request_data" dc:"请求数据"`
ResponseData string `json:"response_data" dc:"响应数据"`
Ip string `json:"ip" dc:"IP地址"`
UserAgent string `json:"user_agent" dc:"用户代理"`
Status int `json:"status" dc:"状态1成功0失败"`
ErrorMsg string `json:"error_msg" dc:"错误信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// UserLogDeleteReq 删除用户日志请求
type UserLogDeleteReq struct {
g.Meta `path:"/user-log/delete" method:"post" tags:"用户日志" summary:"删除用户日志"`
Id int `json:"id" v:"required|min:1" dc:"日志ID"`
}
// UserLogDeleteRes 删除用户日志响应
type UserLogDeleteRes struct {
Message string `json:"message" dc:"操作结果"`
}
// UserLogBatchDeleteReq 批量删除用户日志请求
type UserLogBatchDeleteReq struct {
g.Meta `path:"/user-log/batch-delete" method:"post" tags:"用户日志" summary:"批量删除用户日志"`
Ids []int `json:"ids" v:"required" dc:"日志ID列表"`
}
// UserLogBatchDeleteRes 批量删除用户日志响应
type UserLogBatchDeleteRes struct {
Message string `json:"message" dc:"操作结果"`
}
// UserLogClearReq 清空用户日志请求
type UserLogClearReq struct {
g.Meta `path:"/user-log/clear" method:"post" tags:"用户日志" summary:"清空用户日志"`
Days int `json:"days" dc:"保留天数0表示全部清空"`
UserId int `json:"user_id" dc:"用户ID0表示所有用户"`
Module string `json:"module" dc:"模块名称,空表示所有模块"`
}
// UserLogClearRes 清空用户日志响应
type UserLogClearRes struct {
Message string `json:"message" dc:"操作结果"`
Count int `json:"count" dc:"清空数量"`
}
// UserLogExportReq 导出用户日志请求
type UserLogExportReq struct {
g.Meta `path:"/user-log/export" method:"get" tags:"用户日志" summary:"导出用户日志"`
UserId int `json:"user_id" dc:"用户ID"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Status int `json:"status" dc:"状态1成功0失败"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Format string `json:"format" dc:"导出格式excel,csv,json"`
}
// UserLogExportRes 导出用户日志响应
type UserLogExportRes struct {
Content string `json:"content" dc:"导出内容"`
Filename string `json:"filename" dc:"文件名"`
}
// UserLogStatsReq 用户日志统计请求
type UserLogStatsReq struct {
g.Meta `path:"/user-log/stats" method:"get" tags:"用户日志" summary:"获取用户日志统计"`
UserId int `json:"user_id" dc:"用户ID"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Type string `json:"type" dc:"统计类型day,week,month"`
}
// UserLogStatsRes 用户日志统计响应
type UserLogStatsRes struct {
Stats UserLogStatsData `json:"stats" dc:"统计数据"`
}
// UserLogStatsData 用户日志统计数据
type UserLogStatsData struct {
Total int `json:"total" dc:"总数"`
Success int `json:"success" dc:"成功数"`
Failed int `json:"failed" dc:"失败数"`
SuccessRate float64 `json:"success_rate" dc:"成功率"`
ModuleStats []UserLogModuleStats `json:"module_stats" dc:"模块统计"`
ActionStats []UserLogActionStats `json:"action_stats" dc:"操作统计"`
TimeStats []UserLogTimeStats `json:"time_stats" dc:"时间统计"`
UserStats []UserLogUserStats `json:"user_stats" dc:"用户统计"`
}
// UserLogModuleStats 模块统计
type UserLogModuleStats struct {
Module string `json:"module" dc:"模块名称"`
Count int `json:"count" dc:"数量"`
}
// UserLogActionStats 操作统计
type UserLogActionStats struct {
Action string `json:"action" dc:"操作类型"`
Count int `json:"count" dc:"数量"`
}
// UserLogTimeStats 时间统计
type UserLogTimeStats struct {
Time string `json:"time" dc:"时间"`
Count int `json:"count" dc:"数量"`
}
// UserLogUserStats 用户统计
type UserLogUserStats struct {
UserId int `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
Count int `json:"count" dc:"数量"`
}
// ===== 用户端日志查询 =====
// UserMyLogListReq 用户查看自己的日志列表请求
type UserMyLogListReq struct {
g.Meta `path:"/my-log/list" method:"get" tags:"用户日志" summary:"获取我的日志列表"`
Page int `json:"page" v:"min:1" dc:"页码默认1"`
Size int `json:"size" v:"min:1|max:100" dc:"每页数量默认10"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
}
// UserMyLogListRes 用户查看自己的日志列表响应
type UserMyLogListRes struct {
List []UserMyLogItem `json:"list" dc:"日志列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// UserMyLogItem 用户日志项
type UserMyLogItem struct {
Id int `json:"id" dc:"日志ID"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Description string `json:"description" dc:"操作描述"`
Status int `json:"status" dc:"状态1成功0失败"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// UserMyLogDetailReq 用户查看自己的日志详情请求
type UserMyLogDetailReq struct {
g.Meta `path:"/my-log/detail" method:"get" tags:"用户日志" summary:"获取我的日志详情"`
Id int `json:"id" v:"required|min:1" dc:"日志ID"`
}
// UserMyLogDetailRes 用户查看自己的日志详情响应
type UserMyLogDetailRes struct {
Log UserMyLogDetail `json:"log" dc:"日志详情"`
}
// UserMyLogDetail 用户日志详情
type UserMyLogDetail struct {
Id int `json:"id" dc:"日志ID"`
Module string `json:"module" dc:"模块名称"`
Action string `json:"action" dc:"操作类型"`
Description string `json:"description" dc:"操作描述"`
Status int `json:"status" dc:"状态1成功0失败"`
ErrorMsg string `json:"error_msg" dc:"错误信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// ===== 系统日志管理 =====
// SystemLogListReq 系统日志列表请求
type SystemLogListReq struct {
g.Meta `path:"/system-log/list" method:"get" tags:"系统日志" summary:"获取系统日志列表"`
Page int `json:"page" v:"min:1" dc:"页码默认1"`
Size int `json:"size" v:"min:1|max:100" dc:"每页数量默认10"`
Level string `json:"level" dc:"日志级别debug,info,warn,error"`
Module string `json:"module" dc:"模块名称"`
StartTime string `json:"start_time" dc:"开始时间"`
EndTime string `json:"end_time" dc:"结束时间"`
Keyword string `json:"keyword" dc:"关键词搜索"`
}
// SystemLogListRes 系统日志列表响应
type SystemLogListRes struct {
List []SystemLogItem `json:"list" dc:"日志列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// SystemLogItem 系统日志项
type SystemLogItem struct {
Id int `json:"id" dc:"日志ID"`
Level string `json:"level" dc:"日志级别"`
Module string `json:"module" dc:"模块名称"`
Message string `json:"message" dc:"日志消息"`
Context string `json:"context" dc:"上下文信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// SystemLogDetailReq 系统日志详情请求
type SystemLogDetailReq struct {
g.Meta `path:"/system-log/detail" method:"get" tags:"系统日志" summary:"获取系统日志详情"`
Id int `json:"id" v:"required|min:1" dc:"日志ID"`
}
// SystemLogDetailRes 系统日志详情响应
type SystemLogDetailRes struct {
Log SystemLogDetail `json:"log" dc:"日志详情"`
}
// SystemLogDetail 系统日志详情
type SystemLogDetail struct {
Id int `json:"id" dc:"日志ID"`
Level string `json:"level" dc:"日志级别"`
Module string `json:"module" dc:"模块名称"`
Message string `json:"message" dc:"日志消息"`
Context string `json:"context" dc:"上下文信息"`
CreatedAt string `json:"created_at" dc:"创建时间"`
}
// SystemLogClearReq 清空系统日志请求
type SystemLogClearReq struct {
g.Meta `path:"/system-log/clear" method:"post" tags:"系统日志" summary:"清空系统日志"`
Days int `json:"days" dc:"保留天数0表示全部清空"`
Level string `json:"level" dc:"日志级别,空表示所有级别"`
Module string `json:"module" dc:"模块名称,空表示所有模块"`
}
// SystemLogClearRes 清空系统日志响应
type SystemLogClearRes struct {
Message string `json:"message" dc:"操作结果"`
Count int `json:"count" dc:"清空数量"`
}

19
api/v1/log_routes.go Normal file
View File

@@ -0,0 +1,19 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// LogUserRoutes 用户日志路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func LogUserRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}
// LogAdminRoutes 管理员日志路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func LogAdminRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}

65
api/v1/movie.go Normal file
View File

@@ -0,0 +1,65 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/controller/movie"
)
// MovieGroup 影片管理路由组
func MovieGroup(group *ghttp.RouterGroup) {
group.Middleware(AuthMiddleware) // 需要认证
// 影片管理路由
group.Group("/movies", func(group *ghttp.RouterGroup) {
// 基础CRUD操作
group.GET("/", movie.Movie.GetList) // 获取影片列表
group.POST("/", movie.Movie.Create) // 创建影片
group.GET("/{id}", movie.Movie.GetById) // 获取影片详情
group.POST("/update", movie.Movie.Update) // 更新影片
group.POST("/delete/{id}", movie.Movie.Delete) // 删除影片
// 搜索和筛选
group.GET("/search", movie.Movie.Search) // 搜索影片
group.GET("/category/{category_id}", movie.Movie.GetByCategory) // 按分类获取
// 特殊列表
group.GET("/hot", movie.Movie.GetHot) // 获取热门影片
group.GET("/recommend", movie.Movie.GetRecommend) // 获取推荐影片
group.GET("/new", movie.Movie.GetNew) // 获取最新影片
// 批量操作
group.POST("/batch-update", movie.Movie.BatchUpdate) // 批量更新状态
// 文件上传
group.POST("/upload/video", movie.Movie.UploadVideo) // 上传视频
group.POST("/upload/poster", movie.Movie.UploadPoster) // 上传封面
})
// 集数管理路由
group.Group("/episodes", func(group *ghttp.RouterGroup) {
// 基础CRUD操作
group.POST("/", movie.Episode.Create) // 创建集数
group.GET("/{id}", movie.Episode.GetById) // 获取集数详情
group.POST("/update", movie.Episode.Update) // 更新集数
group.POST("/delete/{id}", movie.Episode.Delete) // 删除集数
// 按影片获取集数
group.GET("/movie/{movie_id}", movie.Episode.GetByMovieId) // 获取影片的所有集数
// 批量操作
group.POST("/batch", movie.Episode.BatchCreate) // 批量创建集数
group.POST("/batch-status", movie.Episode.BatchUpdateStatus) // 批量更新状态
// 文件上传和处理
group.POST("/upload/video", movie.Episode.UploadVideo) // 上传集数视频
group.POST("/thumbnail", movie.Episode.GenerateThumbnail) // 生成缩略图
group.GET("/video/info", movie.Episode.GetVideoInfo) // 获取视频信息
})
}
// AuthMiddleware 认证中间件(这里引用已存在的中间件)
var AuthMiddleware = func(r *ghttp.Request) {
// 这里应该引用已存在的认证中间件
// 暂时跳过认证检查,实际项目中需要实现
r.Middleware.Next()
}

230
api/v1/payment_order.go Normal file
View File

@@ -0,0 +1,230 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
// PaymentOrderCreateReq 创建支付订单请求
type PaymentOrderCreateReq struct {
g.Meta `path:"/payment/create" method:"post" summary:"创建支付订单" tags:"支付订单管理"`
VipLevelId uint `json:"vip_level_id" v:"required|min:1#VIP等级ID不能为空|VIP等级ID必须大于0" dc:"VIP等级ID"`
PaymentType int `json:"payment_type" v:"required|in:1,2,3#支付方式不能为空|支付方式错误" dc:"支付方式(1:支付宝,2:微信,3:余额)"`
CouponId uint `json:"coupon_id" v:"min:0#优惠券ID必须大于等于0" dc:"优惠券ID" default:"0"`
Remark string `json:"remark" v:"length:0,200#备注长度不能超过200字符" dc:"备注"`
}
// PaymentOrderCreateRes 创建支付订单响应
type PaymentOrderCreateRes struct {
g.Meta `mime:"application/json"`
OrderNo string `json:"order_no" dc:"订单号"`
PaymentNo string `json:"payment_no" dc:"支付单号"`
PayUrl string `json:"pay_url" dc:"支付链接"`
Amount string `json:"amount" dc:"支付金额"`
}
// PaymentOrderListReq 支付订单列表请求
type PaymentOrderListReq struct {
g.Meta `path:"/payment/list" method:"get" summary:"支付订单列表" tags:"支付订单管理"`
Status int `json:"status" v:"in:-1,0,1,2,3#状态值错误" dc:"状态(-1:全部,0:待支付,1:已支付,2:已取消,3:已退款)" default:"-1"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// PaymentOrderListRes 支付订单列表响应
type PaymentOrderListRes struct {
g.Meta `mime:"application/json"`
List []PaymentOrderItem `json:"list" dc:"订单列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// PaymentOrderItem 支付订单项目
type PaymentOrderItem struct {
Id uint `json:"id" dc:"订单ID"`
OrderNo string `json:"order_no" dc:"订单号"`
PaymentNo string `json:"payment_no" dc:"支付单号"`
VipLevelName string `json:"vip_level_name" dc:"VIP等级名称"`
OriginalPrice string `json:"original_price" dc:"原价"`
CouponAmount string `json:"coupon_amount" dc:"优惠金额"`
ActualAmount string `json:"actual_amount" dc:"实付金额"`
PaymentType int `json:"payment_type" dc:"支付方式"`
Status int `json:"status" dc:"订单状态"`
PaidAt string `json:"paid_at" dc:"支付时间"`
CreatedAt string `json:"created_at" dc:"创建时间"`
Remark string `json:"remark" dc:"备注"`
}
// PaymentOrderDetailReq 支付订单详情请求
type PaymentOrderDetailReq struct {
g.Meta `path:"/payment/detail" method:"get" summary:"支付订单详情" tags:"支付订单管理"`
OrderNo string `json:"order_no" v:"required#订单号不能为空" dc:"订单号"`
}
// PaymentOrderDetailRes 支付订单详情响应
type PaymentOrderDetailRes struct {
g.Meta `mime:"application/json"`
Order PaymentOrderDetail `json:"order" dc:"订单详情"`
}
// PaymentOrderDetail 支付订单详情
type PaymentOrderDetail struct {
Id uint `json:"id" dc:"订单ID"`
OrderNo string `json:"order_no" dc:"订单号"`
PaymentNo string `json:"payment_no" dc:"支付单号"`
VipLevelId uint `json:"vip_level_id" dc:"VIP等级ID"`
VipLevelName string `json:"vip_level_name" dc:"VIP等级名称"`
Duration int `json:"duration" dc:"时长(天)"`
OriginalPrice string `json:"original_price" dc:"原价"`
CouponId uint `json:"coupon_id" dc:"优惠券ID"`
CouponAmount string `json:"coupon_amount" dc:"优惠金额"`
ActualAmount string `json:"actual_amount" dc:"实付金额"`
PaymentType int `json:"payment_type" dc:"支付方式"`
Status int `json:"status" dc:"订单状态"`
PaidAt string `json:"paid_at" dc:"支付时间"`
CreatedAt string `json:"created_at" dc:"创建时间"`
UpdatedAt string `json:"updated_at" dc:"更新时间"`
Remark string `json:"remark" dc:"备注"`
}
// PaymentOrderCancelReq 取消支付订单请求
type PaymentOrderCancelReq struct {
g.Meta `path:"/payment/cancel" method:"post" summary:"取消支付订单" tags:"支付订单管理"`
OrderNo string `json:"order_no" v:"required#订单号不能为空" dc:"订单号"`
}
// PaymentOrderCancelRes 取消支付订单响应
type PaymentOrderCancelRes struct {
g.Meta `mime:"application/json"`
}
// PaymentCallbackReq 支付回调请求
type PaymentCallbackReq struct {
g.Meta `path:"/payment/callback" method:"post" summary:"支付回调" tags:"支付订单管理"`
OrderNo string `json:"order_no" v:"required#订单号不能为空" dc:"订单号"`
PaymentNo string `json:"payment_no" v:"required#支付单号不能为空" dc:"支付单号"`
Amount string `json:"amount" v:"required#支付金额不能为空" dc:"支付金额"`
Status int `json:"status" v:"required|in:1,2#支付状态不能为空|支付状态错误" dc:"支付状态(1:成功,2:失败)"`
TradeNo string `json:"trade_no" dc:"第三方交易号"`
}
// PaymentCallbackRes 支付回调响应
type PaymentCallbackRes struct {
g.Meta `mime:"application/json"`
}
// AdminPaymentOrderListReq 管理员支付订单列表请求
type AdminPaymentOrderListReq struct {
g.Meta `path:"/admin/payment/list" method:"get" summary:"管理员支付订单列表" tags:"支付订单管理"`
UserId uint `json:"user_id" v:"min:0#用户ID必须大于等于0" dc:"用户ID" default:"0"`
Status int `json:"status" v:"in:-1,0,1,2,3#状态值错误" dc:"状态(-1:全部,0:待支付,1:已支付,2:已取消,3:已退款)" default:"-1"`
PaymentType int `json:"payment_type" v:"in:-1,1,2,3#支付方式错误" dc:"支付方式(-1:全部,1:支付宝,2:微信,3:余额)" default:"-1"`
StartDate string `json:"start_date" v:"date#开始日期格式错误" dc:"开始日期"`
EndDate string `json:"end_date" v:"date#结束日期格式错误" dc:"结束日期"`
Keyword string `json:"keyword" dc:"关键词搜索(订单号/用户名)"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// AdminPaymentOrderListRes 管理员支付订单列表响应
type AdminPaymentOrderListRes struct {
g.Meta `mime:"application/json"`
List []AdminPaymentOrderItem `json:"list" dc:"订单列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// AdminPaymentOrderItem 管理员支付订单项目
type AdminPaymentOrderItem struct {
Id uint `json:"id" dc:"订单ID"`
OrderNo string `json:"order_no" dc:"订单号"`
PaymentNo string `json:"payment_no" dc:"支付单号"`
UserId uint `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
VipLevelName string `json:"vip_level_name" dc:"VIP等级名称"`
OriginalPrice string `json:"original_price" dc:"原价"`
CouponAmount string `json:"coupon_amount" dc:"优惠金额"`
ActualAmount string `json:"actual_amount" dc:"实付金额"`
PaymentType int `json:"payment_type" dc:"支付方式"`
Status int `json:"status" dc:"订单状态"`
PaidAt string `json:"paid_at" dc:"支付时间"`
CreatedAt string `json:"created_at" dc:"创建时间"`
Remark string `json:"remark" dc:"备注"`
}
// AdminPaymentOrderDetailReq 管理员支付订单详情请求
type AdminPaymentOrderDetailReq struct {
g.Meta `path:"/admin/payment/detail" method:"get" summary:"管理员支付订单详情" tags:"支付订单管理"`
Id uint `json:"id" v:"required|min:1#订单ID不能为空|订单ID必须大于0" dc:"订单ID"`
}
// AdminPaymentOrderDetailRes 管理员支付订单详情响应
type AdminPaymentOrderDetailRes struct {
g.Meta `mime:"application/json"`
Order AdminPaymentOrderDetail `json:"order" dc:"订单详情"`
}
// AdminPaymentOrderDetail 管理员支付订单详情
type AdminPaymentOrderDetail struct {
Id uint `json:"id" dc:"订单ID"`
OrderNo string `json:"order_no" dc:"订单号"`
PaymentNo string `json:"payment_no" dc:"支付单号"`
UserId uint `json:"user_id" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
VipLevelId uint `json:"vip_level_id" dc:"VIP等级ID"`
VipLevelName string `json:"vip_level_name" dc:"VIP等级名称"`
Duration int `json:"duration" dc:"时长(天)"`
OriginalPrice string `json:"original_price" dc:"原价"`
CouponId uint `json:"coupon_id" dc:"优惠券ID"`
CouponAmount string `json:"coupon_amount" dc:"优惠金额"`
ActualAmount string `json:"actual_amount" dc:"实付金额"`
PaymentType int `json:"payment_type" dc:"支付方式"`
Status int `json:"status" dc:"订单状态"`
TradeNo string `json:"trade_no" dc:"第三方交易号"`
PaidAt string `json:"paid_at" dc:"支付时间"`
CreatedAt string `json:"created_at" dc:"创建时间"`
UpdatedAt string `json:"updated_at" dc:"更新时间"`
Remark string `json:"remark" dc:"备注"`
}
// AdminPaymentOrderRefundReq 管理员订单退款请求
type AdminPaymentOrderRefundReq struct {
g.Meta `path:"/admin/payment/refund" method:"post" summary:"订单退款" tags:"支付订单管理"`
Id uint `json:"id" v:"required|min:1#订单ID不能为空|订单ID必须大于0" dc:"订单ID"`
RefundType int `json:"refund_type" v:"required|in:1,2#退款类型不能为空|退款类型错误" dc:"退款类型(1:全额退款,2:部分退款)"`
Amount string `json:"amount" v:"required-if:refund_type,2#部分退款时金额不能为空" dc:"退款金额"`
Reason string `json:"reason" v:"required|length:1,200#退款原因不能为空|退款原因长度为1-200字符" dc:"退款原因"`
}
// AdminPaymentOrderRefundRes 管理员订单退款响应
type AdminPaymentOrderRefundRes struct {
g.Meta `mime:"application/json"`
}
// PaymentStatisticsReq 支付统计请求
type PaymentStatisticsReq struct {
g.Meta `path:"/admin/payment/statistics" method:"get" summary:"支付统计" tags:"支付订单管理"`
StartDate string `json:"start_date" v:"date#开始日期格式错误" dc:"开始日期"`
EndDate string `json:"end_date" v:"date#结束日期格式错误" dc:"结束日期"`
Type string `json:"type" v:"in:day,week,month#统计类型错误" dc:"统计类型(day:按天,week:按周,month:按月)" default:"day"`
}
// PaymentStatisticsRes 支付统计响应
type PaymentStatisticsRes struct {
g.Meta `mime:"application/json"`
TotalCount int `json:"total_count" dc:"总订单数"`
TotalAmount string `json:"total_amount" dc:"总金额"`
PaidCount int `json:"paid_count" dc:"已支付订单数"`
PaidAmount string `json:"paid_amount" dc:"已支付金额"`
RefundCount int `json:"refund_count" dc:"退款订单数"`
RefundAmount string `json:"refund_amount" dc:"退款金额"`
ChartData []PaymentStatisticsItem `json:"chart_data" dc:"图表数据"`
}
// PaymentStatisticsItem 支付统计项目
type PaymentStatisticsItem struct {
Date string `json:"date" dc:"日期"`
Count int `json:"count" dc:"订单数"`
Amount string `json:"amount" dc:"金额"`
}

View File

@@ -0,0 +1,19 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// PaymentOrderUserRoutes 用户支付订单路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func PaymentOrderUserRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}
// PaymentOrderAdminRoutes 管理员支付订单路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func PaymentOrderAdminRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}

64
api/v1/user_collect.go Normal file
View File

@@ -0,0 +1,64 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
// UserCollectAddReq 添加收藏请求
type UserCollectAddReq struct {
g.Meta `path:"/user/collect/add" method:"post" summary:"添加收藏" tags:"用户收藏"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
}
// UserCollectAddRes 添加收藏响应
type UserCollectAddRes struct {
g.Meta `mime:"application/json"`
}
// UserCollectRemoveReq 取消收藏请求
type UserCollectRemoveReq struct {
g.Meta `path:"/user/collect/remove" method:"post" summary:"取消收藏" tags:"用户收藏"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
}
// UserCollectRemoveRes 取消收藏响应
type UserCollectRemoveRes struct {
g.Meta `mime:"application/json"`
}
// UserCollectListReq 收藏列表请求
type UserCollectListReq struct {
g.Meta `path:"/user/collect/list" method:"get" summary:"收藏列表" tags:"用户收藏"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// UserCollectListRes 收藏列表响应
type UserCollectListRes struct {
g.Meta `mime:"application/json"`
List []UserCollectItem `json:"list" dc:"收藏列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// UserCollectItem 收藏项目
type UserCollectItem struct {
Id uint `json:"id" dc:"收藏ID"`
MovieId int `json:"movie_id" dc:"影片ID"`
MovieName string `json:"movie_name" dc:"影片名称"`
MovieCover string `json:"movie_cover" dc:"影片封面"`
CreatedAt string `json:"created_at" dc:"收藏时间"`
}
// UserCollectCheckReq 检查收藏状态请求
type UserCollectCheckReq struct {
g.Meta `path:"/user/collect/check" method:"get" summary:"检查收藏状态" tags:"用户收藏"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
}
// UserCollectCheckRes 检查收藏状态响应
type UserCollectCheckRes struct {
g.Meta `mime:"application/json"`
IsCollected bool `json:"is_collected" dc:"是否已收藏"`
}

View File

@@ -0,0 +1,30 @@
package v1
import (
"nl-video-api/api/middleware"
"nl-video-api/internal/controller/user"
"github.com/gogf/gf/v2/net/ghttp"
)
// UserCollectGroup 用户收藏路由组
func UserCollectGroup(group *ghttp.RouterGroup) {
group.Group("/user/collect", func(group *ghttp.RouterGroup) {
// 应用中间件
group.Middleware(middleware.CORS)
group.Middleware(middleware.Auth) // 用户认证中间件
group.Middleware(middleware.RequestLog)
// 添加收藏
group.POST("/add", user.UserCollect.Add)
// 取消收藏
group.POST("/remove", user.UserCollect.Remove)
// 收藏列表
group.GET("/list", user.UserCollect.List)
// 检查收藏状态
group.GET("/check", user.UserCollect.Check)
})
}

View File

@@ -0,0 +1,80 @@
package v1
import (
"github.com/gogf/gf/v2/frame/g"
)
// UserWatchHistoryAddReq 添加观看历史请求
type UserWatchHistoryAddReq struct {
g.Meta `path:"/user/history/add" method:"post" summary:"添加观看历史" tags:"观看历史"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
EpisodeId int `json:"episode_id" v:"min:0#剧集ID必须大于等于0" dc:"剧集ID"`
Progress int `json:"progress" v:"min:0|max:100#观看进度必须在0-100之间" dc:"观看进度(百分比)" default:"0"`
}
// UserWatchHistoryAddRes 添加观看历史响应
type UserWatchHistoryAddRes struct {
g.Meta `mime:"application/json"`
}
// UserWatchHistoryListReq 观看历史列表请求
type UserWatchHistoryListReq struct {
g.Meta `path:"/user/history/list" method:"get" summary:"观看历史列表" tags:"观看历史"`
Page int `json:"page" v:"min:1#页码必须大于0" dc:"页码" default:"1"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100" dc:"每页数量" default:"10"`
}
// UserWatchHistoryListRes 观看历史列表响应
type UserWatchHistoryListRes struct {
g.Meta `mime:"application/json"`
List []UserWatchHistoryItem `json:"list" dc:"观看历史列表"`
Total int `json:"total" dc:"总数"`
Page int `json:"page" dc:"当前页"`
Size int `json:"size" dc:"每页数量"`
}
// UserWatchHistoryItem 观看历史项目
type UserWatchHistoryItem struct {
Id uint `json:"id" dc:"历史记录ID"`
MovieId int `json:"movie_id" dc:"影片ID"`
MovieName string `json:"movie_name" dc:"影片名称"`
MovieCover string `json:"movie_cover" dc:"影片封面"`
EpisodeId int `json:"episode_id" dc:"剧集ID"`
EpisodeName string `json:"episode_name" dc:"剧集名称"`
Progress int `json:"progress" dc:"观看进度"`
WatchedAt string `json:"watched_at" dc:"观看时间"`
}
// UserWatchHistoryDeleteReq 删除观看历史请求
type UserWatchHistoryDeleteReq struct {
g.Meta `path:"/user/history/delete" method:"post" summary:"删除观看历史" tags:"观看历史"`
Id uint `json:"id" v:"required|min:1#历史记录ID不能为空|历史记录ID必须大于0" dc:"历史记录ID"`
}
// UserWatchHistoryDeleteRes 删除观看历史响应
type UserWatchHistoryDeleteRes struct {
g.Meta `mime:"application/json"`
}
// UserWatchHistoryClearReq 清空观看历史请求
type UserWatchHistoryClearReq struct {
g.Meta `path:"/user/history/clear" method:"post" summary:"清空观看历史" tags:"观看历史"`
}
// UserWatchHistoryClearRes 清空观看历史响应
type UserWatchHistoryClearRes struct {
g.Meta `mime:"application/json"`
}
// UserWatchHistoryGetReq 获取观看进度请求
type UserWatchHistoryGetReq struct {
g.Meta `path:"/user/history/get" method:"get" summary:"获取观看进度" tags:"观看历史"`
MovieId int `json:"movie_id" v:"required|min:1#影片ID不能为空|影片ID必须大于0" dc:"影片ID"`
EpisodeId int `json:"episode_id" v:"min:0#剧集ID必须大于等于0" dc:"剧集ID"`
}
// UserWatchHistoryGetRes 获取观看进度响应
type UserWatchHistoryGetRes struct {
g.Meta `mime:"application/json"`
Progress int `json:"progress" dc:"观看进度"`
}

View File

@@ -0,0 +1,33 @@
package v1
import (
"nl-video-api/api/middleware"
"nl-video-api/internal/controller/user"
"github.com/gogf/gf/v2/net/ghttp"
)
// UserWatchHistoryGroup 用户观看历史路由组
func UserWatchHistoryGroup(group *ghttp.RouterGroup) {
group.Group("/user/history", func(group *ghttp.RouterGroup) {
// 应用中间件
group.Middleware(middleware.CORS)
group.Middleware(middleware.Auth) // 用户认证中间件
group.Middleware(middleware.RequestLog)
// 添加观看历史
group.POST("/add", user.UserWatchHistory.Add)
// 观看历史列表
group.GET("/list", user.UserWatchHistory.List)
// 删除观看历史
group.POST("/delete", user.UserWatchHistory.Delete)
// 清空观看历史
group.POST("/clear", user.UserWatchHistory.Clear)
// 获取观看进度
group.GET("/get", user.UserWatchHistory.Get)
})
}

227
api/v1/vip_level.go Normal file
View File

@@ -0,0 +1,227 @@
package v1
// VIP等级管理相关请求和响应结构
// VipLevelCreateReq 创建VIP等级请求
type VipLevelCreateReq struct {
Name string `json:"name" v:"required|length:1,50#VIP等级名称不能为空|VIP等级名称长度为1-50个字符"`
Level int `json:"level" v:"required|min:1#VIP等级不能为空|VIP等级必须大于0"`
Duration int `json:"duration" v:"required|min:1#有效期不能为空|有效期必须大于0天"`
Price string `json:"price" v:"required|regex:^\\d+(\\.\\d{1,2})?$#价格不能为空|价格格式不正确"`
Description string `json:"description" v:"max:500#描述长度不能超过500个字符"`
Features string `json:"features" v:"max:1000#特权描述长度不能超过1000个字符"`
Sort int `json:"sort" v:"min:0#排序值不能小于0"`
Status int `json:"status" v:"in:0,1#状态值只能为0或1"`
}
// VipLevelCreateRes 创建VIP等级响应
type VipLevelCreateRes struct {
Id uint `json:"id"`
}
// VipLevelUpdateReq 更新VIP等级请求
type VipLevelUpdateReq struct {
Id uint `json:"id" v:"required|min:1#VIP等级ID不能为空"`
Name string `json:"name" v:"required|length:1,50#VIP等级名称不能为空|VIP等级名称长度为1-50个字符"`
Level int `json:"level" v:"required|min:1#VIP等级不能为空|VIP等级必须大于0"`
Duration int `json:"duration" v:"required|min:1#有效期不能为空|有效期必须大于0天"`
Price string `json:"price" v:"required|regex:^\\d+(\\.\\d{1,2})?$#价格不能为空|价格格式不正确"`
Description string `json:"description" v:"max:500#描述长度不能超过500个字符"`
Features string `json:"features" v:"max:1000#特权描述长度不能超过1000个字符"`
Sort int `json:"sort" v:"min:0#排序值不能小于0"`
Status int `json:"status" v:"in:0,1#状态值只能为0或1"`
}
// VipLevelListReq 获取VIP等级列表请求
type VipLevelListReq struct {
Page int `json:"page" v:"min:1#页码必须大于0"`
Size int `json:"size" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100"`
Status int `json:"status" v:"in:-1,0,1#状态值只能为-1,0,1"`
Keyword string `json:"keyword" v:"max:50#关键词长度不能超过50个字符"`
MinPrice string `json:"min_price" v:"regex:^\\d*(\\.\\d{1,2})?$#最低价格格式不正确"`
MaxPrice string `json:"max_price" v:"regex:^\\d*(\\.\\d{1,2})?$#最高价格格式不正确"`
}
// VipLevelListRes 获取VIP等级列表响应
type VipLevelListRes struct {
List []VipLevelItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
// VipLevelItem VIP等级列表项
type VipLevelItem struct {
Id uint `json:"id"`
Name string `json:"name"`
Level int `json:"level"`
Duration int `json:"duration"`
Price string `json:"price"`
Description string `json:"description"`
Features string `json:"features"`
Sort int `json:"sort"`
Status int `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// VipLevelDetailReq 获取VIP等级详情请求
type VipLevelDetailReq struct {
Id uint `json:"id" v:"required|min:1#VIP等级ID不能为空"`
}
// VipLevelDetailRes 获取VIP等级详情响应
type VipLevelDetailRes struct {
VipLevel VipLevelDetail `json:"vip_level"`
}
// VipLevelDetail VIP等级详情
type VipLevelDetail struct {
Id uint `json:"id"`
Name string `json:"name"`
Level int `json:"level"`
Duration int `json:"duration"`
Price string `json:"price"`
Description string `json:"description"`
Features string `json:"features"`
Sort int `json:"sort"`
Status int `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// VipLevelDeleteReq 删除VIP等级请求
type VipLevelDeleteReq struct {
Id uint `json:"id" v:"required|min:1#VIP等级ID不能为空"`
}
// VipLevelStatusReq 更新VIP等级状态请求
type VipLevelStatusReq struct {
Id uint `json:"id" v:"required|min:1#VIP等级ID不能为空"`
Status int `json:"status" v:"in:0,1#状态值只能为0或1"`
}
// VipLevelBatchStatusReq 批量更新VIP等级状态请求
type VipLevelBatchStatusReq struct {
Ids []uint `json:"ids" v:"required|min:1#VIP等级ID列表不能为空"`
Status int `json:"status" v:"in:0,1#状态值只能为0或1"`
}
// VipLevelSortReq 更新VIP等级排序请求
type VipLevelSortReq struct {
Id uint `json:"id" v:"required|min:1#VIP等级ID不能为空"`
Sort int `json:"sort" v:"min:0#排序值不能小于0"`
}
// VipLevelBatchSortReq 批量更新VIP等级排序请求
type VipLevelBatchSortReq struct {
Items []VipLevelSortItem `json:"items" v:"required|min:1#排序项目不能为空"`
}
// VipLevelSortItem 排序项目
type VipLevelSortItem struct {
Id uint `json:"id" v:"required|min:1#VIP等级ID不能为空"`
Sort int `json:"sort" v:"min:0#排序值不能小于0"`
}
// VipLevelActiveListReq 获取有效VIP等级列表请求用户端
type VipLevelActiveListReq struct {
// 无需参数直接获取所有有效的VIP等级
}
// VipLevelActiveListRes 获取有效VIP等级列表响应用户端
type VipLevelActiveListRes struct {
List []VipLevelActiveItem `json:"list"`
}
// VipLevelActiveItem 有效VIP等级项用户端
type VipLevelActiveItem struct {
Id uint `json:"id"`
Name string `json:"name"`
Level int `json:"level"`
Duration int `json:"duration"`
Price string `json:"price"`
Description string `json:"description"`
Features string `json:"features"`
IsRecommend bool `json:"is_recommend"` // 是否推荐
}
// VipLevelStatisticsReq 获取VIP等级统计请求
type VipLevelStatisticsReq struct {
StartDate string `json:"start_date" v:"date#开始日期格式不正确"`
EndDate string `json:"end_date" v:"date#结束日期格式不正确"`
}
// VipLevelStatisticsRes 获取VIP等级统计响应
type VipLevelStatisticsRes struct {
TotalLevels int `json:"total_levels"` // 总等级数
ActiveLevels int `json:"active_levels"` // 有效等级数
TotalSales string `json:"total_sales"` // 总销售额
TotalOrders int `json:"total_orders"` // 总订单数
LevelStats []VipLevelStatItem `json:"level_stats"` // 各等级统计
SalesChart []VipLevelSalesChartItem `json:"sales_chart"` // 销售图表数据
PopularLevels []VipLevelPopularItem `json:"popular_levels"` // 热门等级
}
// VipLevelStatItem VIP等级统计项
type VipLevelStatItem struct {
Id uint `json:"id"`
Name string `json:"name"`
Level int `json:"level"`
OrderCount int `json:"order_count"` // 订单数量
SalesAmount string `json:"sales_amount"` // 销售金额
UserCount int `json:"user_count"` // 用户数量
}
// VipLevelSalesChartItem VIP等级销售图表项
type VipLevelSalesChartItem struct {
Date string `json:"date"` // 日期
Amount string `json:"amount"` // 销售金额
Count int `json:"count"` // 订单数量
}
// VipLevelPopularItem 热门VIP等级项
type VipLevelPopularItem struct {
Id uint `json:"id"`
Name string `json:"name"`
Level int `json:"level"`
Price string `json:"price"`
OrderCount int `json:"order_count"`
Percentage string `json:"percentage"` // 占比
}
// VipLevelCopyReq 复制VIP等级请求
type VipLevelCopyReq struct {
SourceId uint `json:"source_id" v:"required|min:1#源VIP等级ID不能为空"`
Name string `json:"name" v:"required|length:1,50#VIP等级名称不能为空|VIP等级名称长度为1-50个字符"`
Level int `json:"level" v:"required|min:1#VIP等级不能为空|VIP等级必须大于0"`
}
// VipLevelCopyRes 复制VIP等级响应
type VipLevelCopyRes struct {
Id uint `json:"id"`
}
// VipLevelExportReq 导出VIP等级请求
type VipLevelExportReq struct {
Status int `json:"status" v:"in:-1,0,1#状态值只能为-1,0,1"`
StartDate string `json:"start_date" v:"date#开始日期格式不正确"`
EndDate string `json:"end_date" v:"date#结束日期格式不正确"`
}
// VipLevelExportRes 导出VIP等级响应
type VipLevelExportRes struct {
FileUrl string `json:"file_url"` // 导出文件URL
}
// VipLevelImportReq 导入VIP等级请求
type VipLevelImportReq struct {
FileUrl string `json:"file_url" v:"required|url#文件URL不能为空|文件URL格式不正确"`
}
// VipLevelImportRes 导入VIP等级响应
type VipLevelImportRes struct {
SuccessCount int `json:"success_count"` // 成功导入数量
FailCount int `json:"fail_count"` // 失败数量
FailReasons []string `json:"fail_reasons"` // 失败原因
}

View File

@@ -0,0 +1,19 @@
package v1
import (
"github.com/gogf/gf/v2/net/ghttp"
)
// VipLevelUserRoutes 用户VIP等级路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func VipLevelUserRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}
// VipLevelAdminRoutes 管理员VIP等级路由
// 注意这个文件不应该导入controller包避免循环导入
// 路由注册应该在cmd包中进行
func VipLevelAdminRoutes(group *ghttp.RouterGroup) {
// 路由注册逻辑移动到cmd包中
}