初始化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

View File

@@ -0,0 +1,370 @@
package admin
import (
"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/internal/model/entity"
"nl-video-api/utility/crypto"
"nl-video-api/utility/jwt"
"nl-video-api/utility/response"
)
type AdminController struct{}
// AdminLoginReq 管理员登录请求
type AdminLoginReq struct {
Username string `json:"username" v:"required|length:3,20#用户名不能为空|用户名长度为3-20位"`
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度为6-20位"`
}
// AdminLoginRes 管理员登录响应
type AdminLoginRes struct {
Token string `json:"token"`
AdminInfo *entity.NlAdmin `json:"admin_info"`
}
// AdminRegisterReq 管理员注册请求
type AdminRegisterReq struct {
Username string `json:"username" v:"required|length:3,20#用户名不能为空|用户名长度为3-20位"`
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度为6-20位"`
Email string `json:"email" v:"required|email#邮箱不能为空|邮箱格式不正确"`
RealName string `json:"real_name" v:"required|length:2,10#真实姓名不能为空|真实姓名长度为2-10位"`
}
// AdminProfileRes 管理员信息响应
type AdminProfileRes struct {
AdminInfo *entity.NlAdmin `json:"admin_info"`
}
// AdminUpdateReq 更新管理员信息请求
type AdminUpdateReq struct {
Email string `json:"email" v:"email#邮箱格式不正确"`
RealName string `json:"real_name" v:"length:2,10#真实姓名长度为2-10位"`
Avatar string `json:"avatar" v:"url#头像必须是有效的URL"`
}
// Login 管理员登录
func (c *AdminController) Login(r *ghttp.Request) {
ctx := r.Context()
var req AdminLoginReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数错误: "+err.Error())
return
}
// 检查数据库连接
if err := g.DB().PingMaster(); err != nil {
g.Log().Error(ctx, "数据库连接失败:", err)
response.Error(r, response.CodeInternalError, "数据库连接失败,请稍后重试")
return
}
// 查询管理员信息
var admin *entity.NlAdmin
err := g.DB().Model("nl_admin").Where("username", req.Username).Scan(&admin)
if err != nil {
g.Log().Error(ctx, "查询管理员失败:", err)
response.Error(r, response.CodeInternalError, "数据库查询失败")
return
}
if admin == nil {
response.Error(r, response.CodeInvalidParam, "用户名或密码错误")
return
}
// 验证密码
if !crypto.CheckPassword(req.Password, admin.Password) {
response.Error(r, response.CodeInvalidParam, "用户名或密码错误")
return
}
// 检查管理员状态
if admin.Status != 1 {
response.Error(r, response.CodeForbidden, "账号已被禁用")
return
}
// 生成JWT Token
token, err := jwt.GenerateToken(admin.Id, admin.Username, "admin")
if err != nil {
g.Log().Error(ctx, "生成Token失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 更新最后登录时间
now := int(time.Now().Unix())
_, err = g.DB().Model("nl_admin").Where("id", admin.Id).Update(g.Map{
"last_login_time": now,
"last_login_ip": r.GetClientIp(),
"updated_at": now,
})
if err != nil {
g.Log().Error(ctx, "更新登录时间失败:", err)
}
// 格式化管理员信息返回
adminMap := g.Map{
"id": admin.Id,
"username": admin.Username,
"nick_name": admin.NickName,
"avatar": admin.Avatar,
"phone": admin.Phone,
"email": admin.Email,
"role_id": admin.RoleId,
"department": admin.Department,
"status": admin.Status,
"last_login_time": response.FormatTimestamp(now),
"created_at": response.FormatTimestamp(admin.CreatedAt),
"updated_at": response.FormatTimestamp(now),
}
response.Success(r, g.Map{
"token": token,
"admin_info": adminMap,
})
}
// Register 管理员注册
func (c *AdminController) Register(r *ghttp.Request) {
ctx := r.Context()
var req AdminRegisterReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数错误: "+err.Error())
return
}
// 检查用户名是否已存在
count, err := g.DB().Model("nl_admin").Where("username", req.Username).Count()
if err != nil {
g.Log().Error(ctx, "查询管理员失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if count > 0 {
response.Error(r, response.CodeInvalidParam, "用户名已存在")
return
}
// 检查邮箱是否已存在
count, err = g.DB().Model("nl_admin").Where("email", req.Email).Count()
if err != nil {
g.Log().Error(ctx, "查询邮箱失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if count > 0 {
response.Error(r, response.CodeInvalidParam, "邮箱已存在")
return
}
// 加密密码
hashedPassword, err := crypto.HashPassword(req.Password)
if err != nil {
g.Log().Error(ctx, "密码加密失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 创建管理员
now := int(time.Now().Unix())
adminData := g.Map{
"username": req.Username,
"password": hashedPassword,
"email": req.Email,
"nick_name": req.RealName,
"role_id": 1, // 默认角色ID
"status": 1, // 默认启用
"created_at": now,
"updated_at": now,
}
result, err := g.DB().Model("nl_admin").Insert(adminData)
if err != nil {
g.Log().Error(ctx, "创建管理员失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 获取新创建的管理员ID
adminId, err := result.LastInsertId()
if err != nil {
g.Log().Error(ctx, "获取管理员ID失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 生成JWT Token
token, err := jwt.GenerateToken(gconv.Uint(adminId), req.Username, "admin")
if err != nil {
g.Log().Error(ctx, "生成Token失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 查询新创建的管理员信息
var admin *entity.NlAdmin
err = g.DB().Model("nl_admin").Where("id", adminId).Scan(&admin)
if err != nil {
g.Log().Error(ctx, "查询管理员失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 清除密码字段
admin.Password = ""
response.Success(r, AdminLoginRes{
Token: token,
AdminInfo: admin,
})
}
// Profile 获取管理员信息
func (c *AdminController) Profile(r *ghttp.Request) {
ctx := r.Context()
// 从上下文获取管理员ID
adminId := r.GetCtxVar("admin_id")
if adminId == nil {
response.Error(r, response.CodeUnauthorized, "未授权访问")
return
}
// 查询管理员信息
var admin *entity.NlAdmin
err := g.DB().Model("nl_admin").Where("id", adminId).Scan(&admin)
if err != nil {
g.Log().Error(ctx, "查询管理员失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if admin == nil {
response.Error(r, response.CodeNotFound, "管理员不存在")
return
}
// 清除密码字段
admin.Password = ""
response.Success(r, AdminProfileRes{
AdminInfo: admin,
})
}
// UpdateProfile 更新管理员信息
func (c *AdminController) UpdateProfile(r *ghttp.Request) {
ctx := r.Context()
var req AdminUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数错误: "+err.Error())
return
}
// 从上下文获取管理员ID
adminId := r.GetCtxVar("admin_id")
if adminId == nil {
response.Error(r, response.CodeUnauthorized, "未授权访问")
return
}
// 构建更新数据
updateData := g.Map{
"updated_at": int(time.Now().Unix()),
}
if req.Email != "" {
// 检查邮箱是否已被其他管理员使用
count, err := g.DB().Model("nl_admin").Where("email", req.Email).Where("id !=", adminId).Count()
if err != nil {
g.Log().Error(ctx, "查询邮箱失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if count > 0 {
response.Error(r, response.CodeInvalidParam, "邮箱已被使用")
return
}
updateData["email"] = req.Email
}
if req.RealName != "" {
updateData["real_name"] = req.RealName
}
if req.Avatar != "" {
updateData["avatar"] = req.Avatar
}
// 更新管理员信息
_, err := g.DB().Model("nl_admin").Where("id", adminId).Update(updateData)
if err != nil {
g.Log().Error(ctx, "更新管理员信息失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 查询更新后的管理员信息
var admin *entity.NlAdmin
err = g.DB().Model("nl_admin").Where("id", adminId).Scan(&admin)
if err != nil {
g.Log().Error(ctx, "查询管理员失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
// 清除密码字段
admin.Password = ""
response.Success(r, AdminProfileRes{
AdminInfo: admin,
})
}
// Logout 管理员登出
func (c *AdminController) Logout(r *ghttp.Request) {
// 这里可以实现Token黑名单机制
// 目前简单返回成功
response.Success(r, nil)
}
// RefreshToken 刷新Token
func (c *AdminController) RefreshToken(r *ghttp.Request) {
// 从上下文获取管理员ID
adminId := r.GetCtxVar("admin_id")
if adminId == nil {
response.Error(r, response.CodeUnauthorized, "未授权访问")
return
}
// 查询管理员信息获取用户名
var admin *entity.NlAdmin
err := g.DB().Model("nl_admin").Where("id", adminId).Scan(&admin)
if err != nil {
g.Log().Error(r.Context(), "查询管理员失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if admin == nil {
response.Error(r, response.CodeNotFound, "管理员不存在")
return
}
// 生成新的Token
token, err := jwt.GenerateToken(admin.Id, admin.Username, "admin")
if err != nil {
g.Log().Error(r.Context(), "生成Token失败:", err)
response.Error(r, response.CodeInternalError, "系统错误")
return
}
response.Success(r, g.Map{
"token": token,
})
}

View File

@@ -0,0 +1,74 @@
package admin
import (
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service"
)
// AttachmentController 管理员附件管理控制器
type AttachmentController struct{}
// NewAttachmentController 创建管理员附件管理控制器实例
func NewAttachmentController() *AttachmentController {
return &AttachmentController{}
}
// GetList 获取附件列表
func (c *AttachmentController) GetList(r *ghttp.Request) {
service.NewAttachmentService().AdminGetList(r)
}
// GetDetail 获取附件详情
func (c *AttachmentController) GetDetail(r *ghttp.Request) {
service.NewAttachmentService().AdminGetDetail(r)
}
// Update 更新附件
func (c *AttachmentController) Update(r *ghttp.Request) {
service.NewAttachmentService().AdminUpdate(r)
}
// Delete 删除附件
func (c *AttachmentController) Delete(r *ghttp.Request) {
service.NewAttachmentService().AdminDelete(r)
}
// BatchDelete 批量删除附件
func (c *AttachmentController) BatchDelete(r *ghttp.Request) {
service.NewAttachmentService().AdminBatchDelete(r)
}
// Download 下载附件
func (c *AttachmentController) Download(r *ghttp.Request) {
service.NewAttachmentService().AdminDownload(r)
}
// Move 移动附件
func (c *AttachmentController) Move(r *ghttp.Request) {
service.NewAttachmentService().AdminMove(r)
}
// Copy 复制附件
func (c *AttachmentController) Copy(r *ghttp.Request) {
service.NewAttachmentService().AdminCopy(r)
}
// Rename 重命名附件
func (c *AttachmentController) Rename(r *ghttp.Request) {
service.NewAttachmentService().AdminRename(r)
}
// Search 搜索附件
func (c *AttachmentController) Search(r *ghttp.Request) {
service.NewAttachmentService().AdminSearch(r)
}
// GetCategoryList 获取附件分类列表
func (c *AttachmentController) GetCategoryList(r *ghttp.Request) {
service.NewAttachmentService().AdminGetCategoryList(r)
}
// GetStatistics 获取附件统计
func (c *AttachmentController) GetStatistics(r *ghttp.Request) {
service.NewAttachmentService().AdminGetStatistics(r)
}

View File

@@ -0,0 +1,162 @@
package admin
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service"
"nl-video-api/utility/response"
)
var Banner = cAdminBanner{}
type cAdminBanner struct{}
// Create 创建轮播图
func (c *cAdminBanner) Create(r *ghttp.Request) {
service.Banner.AdminCreate(r)
}
// Update 更新轮播图
func (c *cAdminBanner) Update(r *ghttp.Request) {
var req *service.AdminBannerUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = uint(id)
}
}
err := service.Banner.AdminUpdate(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// Delete 删除轮播图
func (c *cAdminBanner) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "轮播图ID无效")
return
}
req := &service.AdminBannerDeleteReq{Id: uint(id)}
err = service.Banner.AdminDelete(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// GetDetail 获取轮播图详情
func (c *cAdminBanner) GetDetail(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "轮播图ID无效")
return
}
req := &service.AdminBannerDetailReq{Id: uint(id)}
result, err := service.Banner.AdminGetDetail(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, result)
}
// GetList 获取轮播图列表
func (c *cAdminBanner) GetList(r *ghttp.Request) {
var req *service.AdminBannerListReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 设置默认分页参数
if req.Page <= 0 {
req.Page = 1
}
if req.Size <= 0 {
req.Size = 10
}
result, err := service.Banner.AdminGetList(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, result)
}
// UpdateStatus 更新轮播图状态
func (c *cAdminBanner) UpdateStatus(r *ghttp.Request) {
var req *service.AdminBannerUpdateStatusReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = uint(id)
}
}
err := service.Banner.AdminUpdateStatus(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "状态更新成功",
})
}
// BatchDelete 批量删除轮播图
func (c *cAdminBanner) BatchDelete(r *ghttp.Request) {
var req *service.AdminBannerBatchDeleteReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, 1001, "轮播图ID列表不能为空")
return
}
err := service.Banner.AdminBatchDelete(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "批量删除成功",
})
}

View File

@@ -0,0 +1,27 @@
package admin
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// CommentController 管理员评论控制器
type CommentController struct{}
var Comment = &CommentController{}
// List 管理员评论列表
func (c *CommentController) List(r *ghttp.Request) {
service.Comment.AdminList(r)
}
// UpdateStatus 更新评论状态
func (c *CommentController) UpdateStatus(r *ghttp.Request) {
service.Comment.AdminUpdateStatus(r)
}
// BatchDelete 批量删除评论
func (c *CommentController) BatchDelete(r *ghttp.Request) {
service.Comment.AdminBatchDelete(r)
}

View File

@@ -0,0 +1,109 @@
package admin
import (
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service"
)
// ConfigController 系统配置管理控制器
type ConfigController struct{}
// NewConfigController 创建系统配置管理控制器实例
func NewConfigController() *ConfigController {
return &ConfigController{}
}
// List 获取配置列表
func (c *ConfigController) List(r *ghttp.Request) {
service.NewConfigService().AdminList(r)
}
// Detail 获取配置详情
func (c *ConfigController) Detail(r *ghttp.Request) {
service.NewConfigService().AdminDetail(r)
}
// Create 创建配置
func (c *ConfigController) Create(r *ghttp.Request) {
service.NewConfigService().AdminCreate(r)
}
// Update 更新配置
func (c *ConfigController) Update(r *ghttp.Request) {
service.NewConfigService().AdminUpdate(r)
}
// Delete 删除配置
func (c *ConfigController) Delete(r *ghttp.Request) {
service.NewConfigService().AdminDelete(r)
}
// BatchDelete 批量删除配置
func (c *ConfigController) BatchDelete(r *ghttp.Request) {
service.NewConfigService().AdminBatchDelete(r)
}
// GetByKey 根据键获取配置
func (c *ConfigController) GetByKey(r *ghttp.Request) {
service.NewConfigService().AdminGetByKey(r)
}
// GetByGroup 根据分组获取配置
func (c *ConfigController) GetByGroup(r *ghttp.Request) {
service.NewConfigService().AdminGetByGroup(r)
}
// Set 设置配置
func (c *ConfigController) Set(r *ghttp.Request) {
service.NewConfigService().AdminSet(r)
}
// BatchSet 批量设置配置
func (c *ConfigController) BatchSet(r *ghttp.Request) {
service.NewConfigService().AdminBatchSet(r)
}
// GetGroupList 获取配置分组列表
func (c *ConfigController) GetGroupList(r *ghttp.Request) {
service.NewConfigService().AdminGetGroupList(r)
}
// Export 导出配置
func (c *ConfigController) Export(r *ghttp.Request) {
service.NewConfigService().AdminExport(r)
}
// Import 导入配置
func (c *ConfigController) Import(r *ghttp.Request) {
service.NewConfigService().AdminImport(r)
}
// Cache 缓存配置
func (c *ConfigController) Cache(r *ghttp.Request) {
service.NewConfigService().AdminCache(r)
}
// ClearCache 清除配置缓存
func (c *ConfigController) ClearCache(r *ghttp.Request) {
service.NewConfigService().AdminClearCache(r)
}
// Validate 验证配置
func (c *ConfigController) Validate(r *ghttp.Request) {
service.NewConfigService().AdminValidate(r)
}
// Backup 备份配置
func (c *ConfigController) Backup(r *ghttp.Request) {
service.NewConfigService().AdminBackup(r)
}
// Restore 恢复配置
func (c *ConfigController) Restore(r *ghttp.Request) {
service.NewConfigService().AdminRestore(r)
}
// GetHistory 获取配置历史
func (c *ConfigController) GetHistory(r *ghttp.Request) {
service.NewConfigService().AdminGetHistory(r)
}

View File

@@ -0,0 +1,88 @@
package admin
import (
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service"
)
// LogController 日志管理控制器
type LogController struct{}
// NewLogController 创建日志管理控制器实例
func NewLogController() *LogController {
return &LogController{}
}
// ===== 管理员日志管理 =====
// AdminLogList 获取管理员日志列表
func (c *LogController) AdminLogList(r *ghttp.Request) {
service.NewLogService().AdminLogList(r)
}
// AdminLogDetail 获取管理员日志详情
func (c *LogController) AdminLogDetail(r *ghttp.Request) {
service.NewLogService().AdminLogDetail(r)
}
// AdminLogDelete 删除管理员日志
func (c *LogController) AdminLogDelete(r *ghttp.Request) {
service.NewLogService().AdminLogDelete(r)
}
// AdminLogBatchDelete 批量删除管理员日志
func (c *LogController) AdminLogBatchDelete(r *ghttp.Request) {
service.NewLogService().AdminLogBatchDelete(r)
}
// AdminLogClear 清空管理员日志
func (c *LogController) AdminLogClear(r *ghttp.Request) {
service.NewLogService().AdminLogClear(r)
}
// AdminLogExport 导出管理员日志
func (c *LogController) AdminLogExport(r *ghttp.Request) {
service.NewLogService().AdminLogExport(r)
}
// AdminLogStats 管理员日志统计
func (c *LogController) AdminLogStats(r *ghttp.Request) {
service.NewLogService().AdminLogStats(r)
}
// ===== 用户日志管理 =====
// UserLogList 获取用户日志列表
func (c *LogController) UserLogList(r *ghttp.Request) {
service.NewLogService().UserLogList(r)
}
// UserLogDetail 获取用户日志详情
func (c *LogController) UserLogDetail(r *ghttp.Request) {
service.NewLogService().UserLogDetail(r)
}
// UserLogDelete 删除用户日志
func (c *LogController) UserLogDelete(r *ghttp.Request) {
service.NewLogService().UserLogDelete(r)
}
// UserLogBatchDelete 批量删除用户日志
func (c *LogController) UserLogBatchDelete(r *ghttp.Request) {
service.NewLogService().UserLogBatchDelete(r)
}
// UserLogClear 清空用户日志
func (c *LogController) UserLogClear(r *ghttp.Request) {
service.NewLogService().UserLogClear(r)
}
// UserLogExport 导出用户日志
func (c *LogController) UserLogExport(r *ghttp.Request) {
service.NewLogService().UserLogExport(r)
}
// UserLogStats 用户日志统计
func (c *LogController) UserLogStats(r *ghttp.Request) {
service.NewLogService().UserLogStats(r)
}

View File

@@ -0,0 +1,74 @@
package admin
import (
"nl-video-api/internal/service"
"nl-video-api/utility/response"
"github.com/gogf/gf/v2/net/ghttp"
)
var PaymentOrder = cAdminPaymentOrder{}
type cAdminPaymentOrder struct{}
// GetList 管理员获取支付订单列表
func (c *cAdminPaymentOrder) GetList(r *ghttp.Request) {
service.NewPaymentOrderService().AdminGetList(r)
}
// GetDetail 管理员获取支付订单详情
func (c *cAdminPaymentOrder) GetDetail(r *ghttp.Request) {
service.NewPaymentOrderService().AdminGetDetail(r)
}
// Refund 管理员订单退款
func (c *cAdminPaymentOrder) Refund(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
reason := r.Get("reason").String()
if id == 0 {
response.Error(r, response.CodeInvalidParam, "订单ID不能为空")
return
}
req := &service.PaymentOrderRefundReq{
Id: id,
Reason: reason,
}
err := service.NewPaymentOrderService().AdminRefund(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, "退款成功")
}
// GetStatistics 获取支付统计
func (c *cAdminPaymentOrder) GetStatistics(r *ghttp.Request) {
startDate := r.Get("start_date").String()
endDate := r.Get("end_date").String()
// 设置默认时间范围
if startDate == "" {
startDate = "2024-01-01"
}
if endDate == "" {
endDate = "2024-12-31"
}
result, err := service.NewPaymentOrderService().GetStatistics(r.Context(), startDate, endDate)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, result)
}
// Create 创建支付订单
func (c *cAdminPaymentOrder) Create(r *ghttp.Request) {
service.NewPaymentOrderService().Create(r)
}

View File

@@ -0,0 +1,245 @@
package admin
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/dao"
"nl-video-api/internal/service/auth"
"nl-video-api/utility/response"
)
// PermissionController 权限控制器
type PermissionController struct{}
var Permission = &PermissionController{}
// Create 创建权限
func (c *PermissionController) Create(r *ghttp.Request) {
var req *auth.PermissionCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
id, err := auth.Permission.Create(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"id": id,
})
}
// Update 更新权限
func (c *PermissionController) Update(r *ghttp.Request) {
var req *auth.PermissionUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, response.CodeInvalidParam, "权限ID无效")
return
}
err := auth.Permission.Update(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, "更新成功")
}
// GetById 获取权限详情
func (c *PermissionController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, response.CodeInvalidParam, "权限ID无效")
return
}
permission, err := auth.Permission.GetById(r.Context(), id)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
if permission == nil {
response.Error(r, response.CodeNotFound, "权限不存在")
return
}
response.Success(r, permission)
}
// GetList 获取权限列表
func (c *PermissionController) GetList(r *ghttp.Request) {
var req *dao.PermissionListReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
permissions, total, err := auth.Permission.GetList(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": permissions,
"total": total,
"page": req.Page,
"page_size": req.PageSize,
})
}
// GetTree 获取权限树形结构
func (c *PermissionController) GetTree(r *ghttp.Request) {
permissions, err := auth.Permission.GetTree(r.Context())
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"tree": permissions,
})
}
// Delete 删除权限
func (c *PermissionController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, response.CodeInvalidParam, "权限ID无效")
return
}
err = auth.Permission.Delete(r.Context(), id)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, "删除成功")
}
// GetMenuPermissions 获取菜单权限
func (c *PermissionController) GetMenuPermissions(r *ghttp.Request) {
permissions, err := auth.Permission.GetMenuPermissions(r.Context())
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": permissions,
})
}
// GetApiPermissions 获取API权限
func (c *PermissionController) GetApiPermissions(r *ghttp.Request) {
permissions, err := auth.Permission.GetApiPermissions(r.Context())
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": permissions,
})
}
// GetUserPermissions 获取用户权限
func (c *PermissionController) GetUserPermissions(r *ghttp.Request) {
userIdStr := r.Get("user_id").String()
userId, err := strconv.Atoi(userIdStr)
if err != nil || userId <= 0 {
response.Error(r, response.CodeInvalidParam, "用户ID无效")
return
}
permissions, err := auth.Permission.GetUserPermissions(r.Context(), userId)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": permissions,
})
}
// CheckPermission 检查权限
func (c *PermissionController) CheckPermission(r *ghttp.Request) {
userIdStr := r.Get("user_id").String()
userId, err := strconv.Atoi(userIdStr)
if err != nil || userId <= 0 {
response.Error(r, response.CodeInvalidParam, "用户ID无效")
return
}
permissionCode := r.Get("permission_code").String()
if permissionCode == "" {
response.Error(r, response.CodeInvalidParam, "权限编码不能为空")
return
}
hasPermission, err := auth.Permission.CheckUserPermission(r.Context(), userId, permissionCode)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"has_permission": hasPermission,
})
}
// CheckApiPermission 检查API权限
func (c *PermissionController) CheckApiPermission(r *ghttp.Request) {
userIdStr := r.Get("user_id").String()
userId, err := strconv.Atoi(userIdStr)
if err != nil || userId <= 0 {
response.Error(r, response.CodeInvalidParam, "用户ID无效")
return
}
apiPath := r.Get("api_path").String()
if apiPath == "" {
response.Error(r, response.CodeInvalidParam, "API路径不能为空")
return
}
method := r.Get("method").String()
if method == "" {
response.Error(r, response.CodeInvalidParam, "请求方法不能为空")
return
}
hasPermission, err := auth.Permission.CheckApiPermission(r.Context(), userId, apiPath, method)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"has_permission": hasPermission,
})
}

View File

@@ -0,0 +1,270 @@
package admin
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/dao"
"nl-video-api/internal/service/auth"
"nl-video-api/utility/response"
)
// RoleController 角色控制器
type RoleController struct{}
var Role = &RoleController{}
// Create 创建角色
func (c *RoleController) Create(r *ghttp.Request) {
var req *auth.RoleCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
id, err := auth.Role.Create(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"id": id,
})
}
// Update 更新角色
func (c *RoleController) Update(r *ghttp.Request) {
var req *auth.RoleUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, response.CodeInvalidParam, "角色ID无效")
return
}
err := auth.Role.Update(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, "更新成功")
}
// GetById 获取角色详情
func (c *RoleController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, response.CodeInvalidParam, "角色ID无效")
return
}
role, err := auth.Role.GetById(r.Context(), id)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
if role == nil {
response.Error(r, response.CodeNotFound, "角色不存在")
return
}
response.Success(r, role)
}
// GetList 获取角色列表
func (c *RoleController) GetList(r *ghttp.Request) {
var req *dao.RoleListReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
roles, total, err := auth.Role.GetList(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": roles,
"total": total,
"page": req.Page,
"page_size": req.PageSize,
})
}
// GetAll 获取所有角色
func (c *RoleController) GetAll(r *ghttp.Request) {
roles, err := auth.Role.GetAll(r.Context())
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": roles,
})
}
// Delete 删除角色
func (c *RoleController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, response.CodeInvalidParam, "角色ID无效")
return
}
err = auth.Role.Delete(r.Context(), id)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, "删除成功")
}
// AssignPermissions 为角色分配权限
func (c *RoleController) AssignPermissions(r *ghttp.Request) {
var req *auth.RolePermissionReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取角色ID
if req.RoleId == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.RoleId = id
}
}
if req.RoleId <= 0 {
response.Error(r, response.CodeInvalidParam, "角色ID无效")
return
}
err := auth.Role.AssignPermissions(r.Context(), req)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, "权限分配成功")
}
// GetRolePermissions 获取角色权限
func (c *RoleController) GetRolePermissions(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, response.CodeInvalidParam, "角色ID无效")
return
}
permissions, err := auth.Role.GetRolePermissions(r.Context(), id)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
// 同时返回权限ID列表方便前端处理
permissionIds, _ := auth.Role.GetRolePermissionIds(r.Context(), id)
response.Success(r, g.Map{
"permissions": permissions,
"permission_ids": permissionIds,
})
}
// BatchUpdateStatus 批量更新角色状态
func (c *RoleController) BatchUpdateStatus(r *ghttp.Request) {
type BatchUpdateReq struct {
Ids []int `json:"ids" v:"required#请选择要操作的角色"`
Status int `json:"status" v:"required|in:0,1#状态只能为0或1"`
}
var req BatchUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, response.CodeInvalidParam, "请选择要操作的角色")
return
}
err := auth.Role.BatchUpdateStatus(r.Context(), req.Ids, req.Status)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"count": len(req.Ids),
})
}
// CopyRole 复制角色
func (c *RoleController) CopyRole(r *ghttp.Request) {
type CopyRoleReq struct {
SourceId int `json:"source_id" v:"required|min:1#源角色ID不能为空"`
Name string `json:"name" v:"required|length:2,50#角色名称不能为空|角色名称长度为2-50位"`
Code string `json:"code" v:"required|length:2,50#角色编码不能为空|角色编码长度为2-50位"`
}
var req CopyRoleReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, "参数解析失败: "+err.Error())
return
}
newRoleId, err := auth.Role.CopyRole(r.Context(), req.SourceId, req.Name, req.Code)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"id": newRoleId,
})
}
// GetRolesByLevel 根据等级获取角色
func (c *RoleController) GetRolesByLevel(r *ghttp.Request) {
levelStr := r.Get("level").String()
level, err := strconv.Atoi(levelStr)
if err != nil || level <= 0 {
response.Error(r, response.CodeInvalidParam, "角色等级无效")
return
}
roles, err := auth.Role.GetRolesByLevel(r.Context(), level)
if err != nil {
response.Error(r, response.CodeError, err.Error())
return
}
response.Success(r, g.Map{
"list": roles,
"level": level,
})
}

View File

@@ -0,0 +1,295 @@
package admin
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"nl-video-api/internal/dao"
"nl-video-api/internal/service/user"
"nl-video-api/utility/crypto"
"nl-video-api/utility/response"
)
var User = cAdminUser{}
type cAdminUser struct{}
// AdminUserCreateReq 管理员创建用户请求
type AdminUserCreateReq struct {
Username string `json:"username" v:"required|length:3,20#用户名不能为空|用户名长度为3-20位"`
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度为6-20位"`
Email string `json:"email" v:"email#邮箱格式不正确"`
Phone string `json:"phone" v:"phone#手机号格式不正确"`
Status int `json:"status" v:"in:0,1#状态值不正确"`
}
// AdminUserUpdateReq 管理员更新用户请求
type AdminUserUpdateReq struct {
Id uint `json:"id" v:"required|min:1#用户ID不能为空"`
Username string `json:"username" v:"length:3,20#用户名长度为3-20位"`
Email string `json:"email" v:"email#邮箱格式不正确"`
Phone string `json:"phone" v:"phone#手机号格式不正确"`
Status int `json:"status" v:"in:0,1#状态值不正确"`
}
// AdminUserDetailReq 管理员获取用户详情请求
type AdminUserDetailReq struct {
Id uint `json:"id" v:"required|min:1#用户ID不能为空"`
}
// AdminUserListReq 管理员获取用户列表请求
type AdminUserListReq struct {
Page int `json:"page" v:"min:1#页码不能小于1"`
Size int `json:"size" v:"min:1|max:100#每页数量不能小于1且不能大于100"`
Username string `json:"username"`
Email string `json:"email"`
Status int `json:"status" v:"in:-1,0,1#状态值不正确"`
}
// AdminUserDeleteReq 管理员删除用户请求
type AdminUserDeleteReq struct {
Id uint `json:"id" v:"required|min:1#用户ID不能为空"`
}
// Create 管理员创建用户
func (c *cAdminUser) Create(r *ghttp.Request) {
var req *AdminUserCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 构造用户创建请求
createReq := &user.UserCreateReq{
Username: req.Username,
Password: req.Password,
Email: req.Email,
Phone: req.Phone,
}
// 调用用户服务创建用户
_, err := user.User.Create(r.Context(), createReq)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "创建成功",
})
}
// Update 管理员更新用户
func (c *cAdminUser) Update(r *ghttp.Request) {
var req *AdminUserUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = uint(id)
}
}
if req.Id == 0 {
response.Error(r, 1001, "用户ID不能为空")
return
}
// 构造用户更新请求
updateReq := &user.UserUpdateReq{
Id: int(req.Id),
Username: req.Username,
Email: req.Email,
Phone: req.Phone,
Status: req.Status,
}
// 调用用户服务更新用户
err := user.User.Update(r.Context(), updateReq)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetDetail 管理员获取用户详情
func (c *cAdminUser) GetDetail(r *ghttp.Request) {
var req *AdminUserDetailReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = uint(id)
}
}
if req.Id == 0 {
response.Error(r, 1001, "用户ID不能为空")
return
}
// 调用用户服务获取用户详情
result, err := user.User.GetById(r.Context(), int(req.Id))
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, result)
}
// GetList 管理员获取用户列表
func (c *cAdminUser) GetList(r *ghttp.Request) {
var req *AdminUserListReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 设置默认分页参数
if req.Page <= 0 {
req.Page = 1
}
if req.Size <= 0 {
req.Size = 10
}
// 构造用户列表请求
listReq := &dao.UserListReq{
Page: req.Page,
Username: req.Username,
Email: req.Email,
Status: req.Status,
}
// 调用用户服务获取用户列表
result, total, err := user.User.GetList(r.Context(), listReq)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
// 构造响应数据
responseData := g.Map{
"list": result,
"total": total,
"page": req.Page,
"size": req.Size,
}
response.Success(r, responseData)
}
// Delete 管理员删除用户
func (c *cAdminUser) Delete(r *ghttp.Request) {
var req *AdminUserDeleteReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = uint(id)
}
}
if req.Id == 0 {
response.Error(r, 1001, "用户ID不能为空")
return
}
// 调用用户服务删除用户
err := user.User.Delete(r.Context(), int(req.Id))
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// UpdateStatus 管理员更新用户状态
func (c *cAdminUser) UpdateStatus(r *ghttp.Request) {
id := r.Get("id").Uint()
status := r.Get("status").Int()
if id == 0 {
response.Error(r, 1001, "用户ID不能为空")
return
}
// 构造用户更新请求
updateReq := &user.UserUpdateReq{
Id: int(id),
Status: status,
}
// 调用用户服务更新用户
err := user.User.Update(r.Context(), updateReq)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "状态更新成功",
})
}
// ResetPassword 管理员重置用户密码
func (c *cAdminUser) ResetPassword(r *ghttp.Request) {
id := r.Get("id").Uint()
newPassword := r.Get("password").String()
if id == 0 {
response.Error(r, 1001, "用户ID不能为空")
return
}
if newPassword == "" {
response.Error(r, 1001, "新密码不能为空")
return
}
// 直接更新密码,管理员重置不需要原密码验证
hashedPassword, err := crypto.HashPassword(newPassword)
if err != nil {
response.Error(r, 1002, "密码加密失败: "+err.Error())
return
}
// 更新用户密码
_, err = g.DB().Model("nl_user").Ctx(r.Context()).Where("id", id).Data(g.Map{
"password": hashedPassword,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "密码重置成功",
})
}

View File

@@ -0,0 +1,59 @@
package admin
import (
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service"
)
// VipLevelController VIP等级控制器管理端
type VipLevelController struct{}
// NewVipLevelController 创建VIP等级控制器实例
func NewVipLevelController() *VipLevelController {
return &VipLevelController{}
}
// Create 创建VIP等级
func (c *VipLevelController) Create(r *ghttp.Request) {
service.VipLevel.AdminCreate(r)
}
// Update 更新VIP等级
func (c *VipLevelController) Update(r *ghttp.Request) {
service.VipLevel.AdminUpdate(r)
}
// List 获取VIP等级列表
func (c *VipLevelController) List(r *ghttp.Request) {
service.VipLevel.AdminGetList(r)
}
// Detail 获取VIP等级详情
func (c *VipLevelController) Detail(r *ghttp.Request) {
service.VipLevel.GetDetail(r)
}
// Delete 删除VIP等级
func (c *VipLevelController) Delete(r *ghttp.Request) {
service.VipLevel.AdminDelete(r)
}
// UpdateStatus 更新VIP等级状态
func (c *VipLevelController) UpdateStatus(r *ghttp.Request) {
service.VipLevel.AdminUpdateStatus(r)
}
// BatchDelete 批量删除VIP等级
func (c *VipLevelController) BatchDelete(r *ghttp.Request) {
service.VipLevel.AdminBatchDelete(r)
}
// GetAll 获取所有VIP等级
func (c *VipLevelController) GetAll(r *ghttp.Request) {
service.VipLevel.GetAll(r)
}
// GetActiveList 获取启用的VIP等级列表
func (c *VipLevelController) GetActiveList(r *ghttp.Request) {
service.VipLevel.GetActiveList(r)
}

View File

@@ -0,0 +1,283 @@
package auth
import (
"nl-video-api/internal/consts"
"nl-video-api/internal/model/entity"
"nl-video-api/utility/crypto"
"nl-video-api/utility/jwt"
"nl-video-api/utility/response"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type cAuth struct{}
var Auth = cAuth{}
// LoginReq 登录请求
type LoginReq struct {
Username string `json:"username" v:"required#用户名不能为空"`
Password string `json:"password" v:"required#密码不能为空"`
}
// RegisterReq 注册请求
type RegisterReq struct {
Username string `json:"username" v:"required|length:3,20#用户名不能为空|用户名长度为3-20位"`
Phone string `json:"phone" v:"required|phone#手机号不能为空|手机号格式错误"`
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度为6-20位"`
Code string `json:"code" v:"required#验证码不能为空"`
}
// UpdateProfileReq 更新资料请求
type UpdateProfileReq struct {
Nickname string `json:"nickname" v:"length:1,20#昵称长度为1-20位"`
Avatar string `json:"avatar" v:"url#头像格式错误"`
Gender int `json:"gender" v:"in:0,1,2#性别参数错误"`
Birthday string `json:"birthday" v:"date#生日格式错误"`
}
// Login 用户登录
func (c *cAuth) Login(r *ghttp.Request) {
var req LoginReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, err.Error())
return
}
// 查询用户
var user entity.NlUser
err := g.DB().Model("nl_user").Where("username = ? OR phone = ?", req.Username, req.Username).Scan(&user)
if err != nil || user.Id == 0 {
response.Error(r, response.CodeError, "用户名或密码错误")
return
}
// 验证密码
if !crypto.CheckPassword(req.Password, user.Password) {
response.Error(r, response.CodeError, "用户名或密码错误")
return
}
// 检查用户状态
if user.Status != consts.UserStatusNormal {
response.Error(r, response.CodeError, "账号已被禁用")
return
}
// 生成Token
token, err := jwt.GenerateToken(user.Id, user.Username, consts.UserTypeUser)
if err != nil {
response.Error(r, response.CodeServerError, "Token生成失败")
return
}
// 更新最后登录信息
now := int(time.Now().Unix())
clientIP := r.GetClientIp()
// 将IPv6地址::1转换为IPv4地址127.0.0.1或者使用IP地址的哈希值
if clientIP == "::1" {
clientIP = "127.0.0.1"
}
g.DB().Model("nl_user").Where("id", user.Id).Update(g.Map{
"last_login_time": now,
"last_login_ip": clientIP,
"login_count": g.DB().Raw("login_count + 1"),
})
// 格式化用户信息返回
userMap := g.Map{
"id": user.Id,
"username": user.Username,
"nick_name": user.NickName,
"avatar": user.Avatar,
"phone": user.Phone,
"email": user.Email,
"gender": user.Gender,
"vip_level": user.VipLevel,
"vip_expire_time": response.FormatTimestamp(user.VipExpireTime),
"balance": user.Balance,
"points": user.Points,
"status": user.Status,
"last_login_time": response.FormatTimestamp(now),
"created_at": response.FormatTimestamp(user.CreatedAt),
"updated_at": response.FormatTimestamp(user.UpdatedAt),
}
response.Success(r, g.Map{
"token": token,
"user": userMap,
})
}
// Register 用户注册
func (c *cAuth) Register(r *ghttp.Request) {
var req RegisterReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, err.Error())
return
}
// 验证验证码(这里简化处理,实际应该验证短信验证码)
if req.Code != "123456" {
response.Error(r, response.CodeError, "验证码错误")
return
}
// 检查用户名是否存在
count, _ := g.DB().Model("nl_user").Where("username", req.Username).Count()
if count > 0 {
response.Error(r, response.CodeError, "用户名已存在")
return
}
// 检查手机号是否存在
count, _ = g.DB().Model("nl_user").Where("phone", req.Phone).Count()
if count > 0 {
response.Error(r, response.CodeError, "手机号已注册")
return
}
// 加密密码
hashedPassword, err := crypto.HashPassword(req.Password)
if err != nil {
response.Error(r, response.CodeServerError, "密码加密失败")
return
}
// 创建用户
now := int(time.Now().Unix())
userId, err := g.DB().Model("nl_user").InsertAndGetId(g.Map{
"username": req.Username,
"nick_name": req.Username,
"phone": req.Phone,
"password": hashedPassword,
"vip_level": consts.VipLevelNormal,
"status": consts.UserStatusNormal,
"created_at": now,
"updated_at": now,
})
if err != nil {
response.Error(r, response.CodeServerError, "注册失败")
return
}
// 生成Token
token, err := jwt.GenerateToken(uint(userId), req.Username, consts.UserTypeUser)
if err != nil {
response.Error(r, response.CodeServerError, "Token生成失败")
return
}
response.Success(r, g.Map{
"token": token,
"user_id": userId,
"message": "注册成功",
})
}
// Profile 获取用户信息
func (c *cAuth) Profile(r *ghttp.Request) {
userId := r.GetCtxVar("user_id").Uint()
var user entity.NlUser
err := g.DB().Model("nl_user").Where("id", userId).Scan(&user)
if err != nil {
response.Error(r, response.CodeServerError, "获取用户信息失败")
return
}
// 格式化用户信息返回
userMap := g.Map{
"id": user.Id,
"username": user.Username,
"nick_name": user.NickName,
"avatar": user.Avatar,
"phone": user.Phone,
"email": user.Email,
"gender": user.Gender,
"birthday": user.Birthday,
"vip_level": user.VipLevel,
"vip_expire_time": response.FormatTimestamp(user.VipExpireTime),
"balance": user.Balance,
"points": user.Points,
"status": user.Status,
"last_login_time": response.FormatTimestamp(user.LastLoginTime),
"login_count": user.LoginCount,
"desc": user.Desc,
"created_at": response.FormatTimestamp(user.CreatedAt),
"updated_at": response.FormatTimestamp(user.UpdatedAt),
}
response.Success(r, userMap)
}
// UpdateProfile 更新用户信息
func (c *cAuth) UpdateProfile(r *ghttp.Request) {
var req UpdateProfileReq
if err := r.Parse(&req); err != nil {
response.Error(r, response.CodeInvalidParam, err.Error())
return
}
userId := r.GetCtxVar("user_id").Uint()
// 构建更新数据
updateData := g.Map{
"updated_at": int(time.Now().Unix()),
}
if req.Nickname != "" {
updateData["nickname"] = req.Nickname
}
if req.Avatar != "" {
updateData["avatar"] = req.Avatar
}
if req.Gender > 0 {
updateData["gender"] = req.Gender
}
if req.Birthday != "" {
updateData["birthday"] = req.Birthday
}
// 更新用户信息
_, err := g.DB().Model("nl_user").Where("id", userId).Update(updateData)
if err != nil {
response.Error(r, response.CodeServerError, "更新失败")
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// Logout 用户登出
func (c *cAuth) Logout(r *ghttp.Request) {
// 这里可以将token加入黑名单简化处理直接返回成功
response.Success(r, g.Map{
"message": "登出成功",
})
}
// RefreshToken 刷新Token
func (c *cAuth) RefreshToken(r *ghttp.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
response.Error(r, response.CodeUnauthorized, "请提供认证令牌")
return
}
tokenString := authHeader[7:] // 去掉 "Bearer "
newToken, err := jwt.RefreshToken(tokenString)
if err != nil {
response.Error(r, response.CodeTokenInvalid, "Token刷新失败")
return
}
response.Success(r, g.Map{
"token": newToken,
})
}

View File

@@ -0,0 +1,5 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package hello

View File

@@ -0,0 +1,16 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package hello
import (
"nl-video-api/api/hello"
)
type ControllerV1 struct{}
func NewV1() hello.IHelloV1 {
return &ControllerV1{}
}

View File

@@ -0,0 +1,13 @@
package hello
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"nl-video-api/api/hello/v1"
)
func (c *ControllerV1) Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) {
g.RequestFromCtx(ctx).Response.Writeln("Hello World!")
return
}

View File

@@ -0,0 +1,337 @@
package movie
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"nl-video-api/internal/dao"
"nl-video-api/internal/service/movie"
"nl-video-api/utility/response"
)
// EpisodeController 集数控制器
type EpisodeController struct{}
var Episode = &EpisodeController{}
// Create 创建集数
func (c *EpisodeController) Create(r *ghttp.Request) {
var req *movie.EpisodeCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
episodeService := movie.NewEpisodeService()
err := episodeService.Create(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "创建成功",
"id": req.MovieId,
})
}
// Update 更新集数
func (c *EpisodeController) Update(r *ghttp.Request) {
var req *movie.EpisodeUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
err := episodeService.Update(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetById 获取集数详情
func (c *EpisodeController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
episode, err := episodeService.GetById(r.Context(), &movie.EpisodeDetailReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": episode,
})
}
// GetByMovieId 根据影片ID获取集数列表
func (c *EpisodeController) GetByMovieId(r *ghttp.Request) {
movieIdStr := r.Get("movie_id").String()
movieId, err := strconv.Atoi(movieIdStr)
if err != nil || movieId <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
episodeService := movie.NewEpisodeService()
episodes, err := episodeService.GetByMovieId(r.Context(), movieId)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"list": episodes,
"total": len(episodes),
"movie_id": movieId,
})
}
// Delete 删除集数
func (c *EpisodeController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
err = episodeService.Delete(r.Context(), &movie.EpisodeDeleteReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// BatchCreate 批量创建集数
func (c *EpisodeController) BatchCreate(r *ghttp.Request) {
type BatchCreateReq struct {
MovieId int `json:"movie_id" v:"required|min:1#请选择影片"`
Episodes []movie.EpisodeCreateReq `json:"episodes" v:"required#集数列表不能为空"`
}
var req BatchCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Episodes) == 0 {
response.Error(r, 1001, "集数列表不能为空")
return
}
// 设置影片ID
for i := range req.Episodes {
req.Episodes[i].MovieId = req.MovieId
}
episodeService := movie.NewEpisodeService()
// 由于BatchCreate方法不存在我们逐个创建
successCount := 0
for _, episodeReq := range req.Episodes {
if err := episodeService.Create(r.Context(), &episodeReq); err != nil {
g.Log().Errorf(r.Context(), "创建集数失败: %v", err)
} else {
successCount++
}
}
response.Success(r, g.Map{
"message": "批量创建完成",
"movie_id": req.MovieId,
"total_count": len(req.Episodes),
"success_count": successCount,
"fail_count": len(req.Episodes) - successCount,
})
}
// UploadVideo 上传集数视频
func (c *EpisodeController) UploadVideo(r *ghttp.Request) {
file := r.GetUploadFile("video")
if file == nil {
response.Error(r, 1001, "请选择要上传的视频文件")
return
}
// 验证文件类型
allowedTypes := []string{"video/mp4", "video/avi", "video/mkv", "video/mov", "video/wmv"}
isValidType := false
for _, allowedType := range allowedTypes {
if file.Header.Get("Content-Type") == allowedType {
isValidType = true
break
}
}
if !isValidType {
response.Error(r, 1001, "不支持的视频格式")
return
}
// 检查文件大小限制5GB
maxSize := int64(5 * 1024 * 1024 * 1024)
if file.Size > maxSize {
response.Error(r, 1001, "视频文件过大最大支持5GB")
return
}
// 生成文件名
timestamp := gtime.Now().TimestampStr()
filename := timestamp + "_" + file.Filename
uploadPath := "resource/public/uploads/episodes/" + filename
// 保存文件
if _, err := file.Save(uploadPath); err != nil {
response.Error(r, 1002, "视频上传失败: "+err.Error())
return
}
// 返回文件信息
relativePath := "/uploads/episodes/" + filename
response.Success(r, g.Map{
"message": "上传成功",
"url": relativePath,
"filename": filename,
"size": file.Size,
})
}
// GenerateThumbnail 生成缩略图
func (c *EpisodeController) GenerateThumbnail(r *ghttp.Request) {
videoUrl := r.Get("video_url").String()
if videoUrl == "" {
response.Error(r, 1001, "视频地址不能为空")
return
}
// 生成缩略图文件路径
timestamp := gtime.Now().TimestampStr()
filename := "thumb_" + timestamp + ".jpg"
thumbDir := "resource/public/uploads/thumbnails"
_ = thumbDir + "/" + filename // 避免未使用变量错误
// 提取缩略图 (这里需要实际的视频处理库)
// if err := video.ExtractCover(videoUrl, thumbPath); err != nil {
// response.Error(r, 1002, "生成缩略图失败: "+err.Error())
// return
// }
// 返回缩略图信息
relativePath := "/uploads/thumbnails/" + filename
response.Success(r, g.Map{
"message": "生成成功",
"thumbnail": relativePath,
"filename": filename,
})
}
// GetVideoInfo 获取视频信息
func (c *EpisodeController) GetVideoInfo(r *ghttp.Request) {
videoUrl := r.Get("video_url").String()
if videoUrl == "" {
response.Error(r, 1001, "视频地址不能为空")
return
}
// 获取视频信息 (这里需要实际的视频处理库)
// videoInfo, err := video.GetVideoInfo(videoUrl)
// if err != nil {
// response.Error(r, 1002, "获取视频信息失败: "+err.Error())
// return
// }
// 模拟返回视频信息
videoInfo := g.Map{
"duration": 0,
"width": 1920,
"height": 1080,
"bitrate": "2000kbps",
"format": "mp4",
"size": 0,
"created_at": "",
}
response.Success(r, g.Map{
"message": "获取成功",
"data": videoInfo,
})
}
// BatchUpdateStatus 批量更新集数状态
func (c *EpisodeController) BatchUpdateStatus(r *ghttp.Request) {
type BatchUpdateReq struct {
Ids []int `json:"ids" v:"required#请选择要操作的集数"`
Status int `json:"status" v:"required|in:0,1#状态只能为0或1"`
}
var req BatchUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, 1001, "请选择要操作的集数")
return
}
ctx := r.Context()
successCount := 0
failCount := 0
for _, id := range req.Ids {
updateData := g.Map{
"status": req.Status,
}
episodeDao := dao.NewEpisodeDao()
if err := episodeDao.Update(ctx, id, updateData); err != nil {
g.Log().Errorf(ctx, "批量更新集数状态失败: ID=%d, 错误=%v", id, err)
failCount++
} else {
successCount++
}
}
response.Success(r, g.Map{
"message": "批量更新完成",
"success_count": successCount,
"fail_count": failCount,
"total_count": len(req.Ids),
})
}

View File

@@ -0,0 +1,418 @@
package movie
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service/movie"
"nl-video-api/utility/response"
)
// MovieController 影片控制器
type MovieController struct{}
var Movie = &MovieController{}
// Create 创建影片
func (c *MovieController) Create(r *ghttp.Request) {
var req *movie.MovieCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
movieService := movie.NewMovieService()
err := movieService.Create(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "创建成功",
})
}
// Update 更新影片
func (c *MovieController) Update(r *ghttp.Request) {
var req *movie.MovieUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
err := movieService.Update(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetById 获取影片详情
func (c *MovieController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
movieDetail, err := movieService.GetById(r.Context(), &movie.MovieDetailReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movieDetail,
})
}
// GetList 获取影片列表
func (c *MovieController) GetList(r *ghttp.Request) {
var req *movie.MovieListReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 设置默认分页参数
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
movieService := movie.NewMovieService()
result, err := movieService.GetList(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": result,
})
}
// Delete 删除影片
func (c *MovieController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
err = movieService.Delete(r.Context(), &movie.MovieDeleteReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// GetHot 获取热门影片
func (c *MovieController) GetHot(r *ghttp.Request) {
limitStr := r.Get("limit", "10").String()
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
movieService := movie.NewMovieService()
movies, err := movieService.GetHotMovies(r.Context(), limit)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movies,
})
}
// GetRecommend 获取推荐影片
func (c *MovieController) GetRecommend(r *ghttp.Request) {
limitStr := r.Get("limit", "10").String()
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
movieService := movie.NewMovieService()
movies, err := movieService.GetRecommendMovies(r.Context(), limit)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movies,
})
}
// GetNew 获取最新影片
func (c *MovieController) GetNew(r *ghttp.Request) {
limitStr := r.Get("limit", "10").String()
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
movieService := movie.NewMovieService()
movies, err := movieService.GetNewMovies(r.Context(), limit)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movies,
})
}
// Search 搜索影片
func (c *MovieController) Search(r *ghttp.Request) {
keyword := r.Get("keyword").String()
if keyword == "" {
response.Error(r, 1001, "搜索关键词不能为空")
return
}
pageStr := r.Get("page", "1").String()
page, err := strconv.Atoi(pageStr)
if err != nil || page <= 0 {
page = 1
}
pageSizeStr := r.Get("page_size", "10").String()
pageSize, err := strconv.Atoi(pageSizeStr)
if err != nil || pageSize <= 0 {
pageSize = 10
}
movieService := movie.NewMovieService()
movies, total, err := movieService.SearchMovies(r.Context(), keyword, page, pageSize)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "搜索成功",
"data": g.Map{
"list": movies,
"total": total,
"page": page,
"page_size": pageSize,
"keyword": keyword,
},
})
}
// GetByCategory 根据分类获取影片
func (c *MovieController) GetByCategory(r *ghttp.Request) {
categoryIdStr := r.Get("category_id").String()
categoryId, err := strconv.Atoi(categoryIdStr)
if err != nil || categoryId <= 0 {
response.Error(r, 1001, "分类ID无效")
return
}
pageStr := r.Get("page", "1").String()
page, err := strconv.Atoi(pageStr)
if err != nil || page <= 0 {
page = 1
}
pageSizeStr := r.Get("page_size", "10").String()
pageSize, err := strconv.Atoi(pageSizeStr)
if err != nil || pageSize <= 0 {
pageSize = 10
}
movieService := movie.NewMovieService()
movies, total, err := movieService.GetMoviesByCategory(r.Context(), categoryId, page, pageSize)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": g.Map{
"list": movies,
"total": total,
"page": page,
"page_size": pageSize,
"category_id": categoryId,
},
})
}
// UpdateViewCount 更新观看次数
func (c *MovieController) UpdateViewCount(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
err = movieService.UpdateViewCount(r.Context(), id)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// UpdateLikeCount 更新点赞数
func (c *MovieController) UpdateLikeCount(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
incrementStr := r.Get("increment", "1").String()
increment, err := strconv.Atoi(incrementStr)
if err != nil {
increment = 1
}
movieService := movie.NewMovieService()
err = movieService.UpdateLikeCount(r.Context(), id, increment)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// UpdateCollectCount 更新收藏数
func (c *MovieController) UpdateCollectCount(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
incrementStr := r.Get("increment", "1").String()
increment, err := strconv.Atoi(incrementStr)
if err != nil {
increment = 1
}
movieService := movie.NewMovieService()
err = movieService.UpdateCollectCount(r.Context(), id, increment)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetStatistics 获取影片统计
func (c *MovieController) GetStatistics(r *ghttp.Request) {
movieService := movie.NewMovieService()
stats, err := movieService.GetStatistics(r.Context())
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": stats,
})
}
// BatchUpdate 批量更新影片
func (c *MovieController) BatchUpdate(r *ghttp.Request) {
var req struct {
Ids []int `json:"ids" v:"required#影片ID列表不能为空"`
Status *int `json:"status"`
IsVip *int `json:"is_vip"`
}
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, 1001, "影片ID列表不能为空")
return
}
// TODO: 实现批量更新逻辑
response.Success(r, g.Map{
"message": "批量更新成功",
})
}
// UploadVideo 上传视频
func (c *MovieController) UploadVideo(r *ghttp.Request) {
// TODO: 实现视频上传逻辑
response.Success(r, g.Map{
"message": "视频上传成功",
"data": g.Map{
"url": "/uploads/videos/example.mp4",
},
})
}
// UploadPoster 上传海报
func (c *MovieController) UploadPoster(r *ghttp.Request) {
// TODO: 实现海报上传逻辑
response.Success(r, g.Map{
"message": "海报上传成功",
"data": g.Map{
"url": "/uploads/posters/example.jpg",
},
})
}

View File

@@ -0,0 +1,64 @@
package user
import (
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service"
)
// AttachmentController 用户附件管理控制器
type AttachmentController struct{}
// NewAttachmentController 创建用户附件管理控制器实例
func NewAttachmentController() *AttachmentController {
return &AttachmentController{}
}
// Upload 上传附件
func (c *AttachmentController) Upload(r *ghttp.Request) {
service.NewAttachmentService().UserUpload(r)
}
// GetList 获取用户附件列表
func (c *AttachmentController) GetList(r *ghttp.Request) {
service.NewAttachmentService().UserGetList(r)
}
// GetDetail 获取附件详情
func (c *AttachmentController) GetDetail(r *ghttp.Request) {
service.NewAttachmentService().UserGetDetail(r)
}
// Update 更新附件
func (c *AttachmentController) Update(r *ghttp.Request) {
service.NewAttachmentService().UserUpdate(r)
}
// Delete 删除附件
func (c *AttachmentController) Delete(r *ghttp.Request) {
service.NewAttachmentService().UserDelete(r)
}
// Download 下载附件
func (c *AttachmentController) Download(r *ghttp.Request) {
service.NewAttachmentService().UserDownload(r)
}
// Copy 复制附件
func (c *AttachmentController) Copy(r *ghttp.Request) {
service.NewAttachmentService().UserCopy(r)
}
// Rename 重命名附件
func (c *AttachmentController) Rename(r *ghttp.Request) {
service.NewAttachmentService().UserRename(r)
}
// Search 搜索附件
func (c *AttachmentController) Search(r *ghttp.Request) {
service.NewAttachmentService().UserSearch(r)
}
// GetCategoryList 获取附件分类列表
func (c *AttachmentController) GetCategoryList(r *ghttp.Request) {
service.NewAttachmentService().UserGetCategoryList(r)
}

View File

@@ -0,0 +1,21 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
var Banner = cBanner{}
type cBanner struct{}
// GetList 获取轮播图列表
func (c *cBanner) GetList(r *ghttp.Request) {
service.Banner.UserGetList(r)
}
// GetDetail 获取轮播图详情
func (c *cBanner) GetDetail(r *ghttp.Request) {
service.Banner.UserGetDetail(r)
}

View File

@@ -0,0 +1,42 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// CommentController 评论控制器
type CommentController struct{}
var Comment = &CommentController{}
// Add 添加评论
func (c *CommentController) Add(r *ghttp.Request) {
service.Comment.Add(r)
}
// List 评论列表
func (c *CommentController) List(r *ghttp.Request) {
service.Comment.GetList(r)
}
// Delete 删除评论
func (c *CommentController) Delete(r *ghttp.Request) {
service.Comment.Delete(r)
}
// Like 点赞评论
func (c *CommentController) Like(r *ghttp.Request) {
service.Comment.Like(r)
}
// Unlike 取消点赞
func (c *CommentController) Unlike(r *ghttp.Request) {
service.Comment.Unlike(r)
}
// Report 举报评论
func (c *CommentController) Report(r *ghttp.Request) {
service.Comment.Report(r)
}

View File

@@ -0,0 +1,22 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// ConfigController 系统配置控制器
type ConfigController struct{}
var Config = &ConfigController{}
// GetList 获取配置列表
func (c *ConfigController) GetList(r *ghttp.Request) {
service.Config.GetList(r)
}
// GetByKey 根据键获取配置
func (c *ConfigController) GetByKey(r *ghttp.Request) {
service.Config.GetByKey(r)
}

View File

@@ -0,0 +1,17 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// LogController 日志控制器
type LogController struct{}
var Log = &LogController{}
// GetList 获取日志列表
func (c *LogController) GetList(r *ghttp.Request) {
service.Log.GetList(r)
}

View File

@@ -0,0 +1,37 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// PaymentOrderController 支付订单控制器
type PaymentOrderController struct{}
var PaymentOrder = &PaymentOrderController{}
// Create 创建支付订单
func (c *PaymentOrderController) Create(r *ghttp.Request) {
service.PaymentOrder.Create(r)
}
// GetList 获取支付订单列表
func (c *PaymentOrderController) GetList(r *ghttp.Request) {
service.PaymentOrder.GetList(r)
}
// GetDetail 获取支付订单详情
func (c *PaymentOrderController) GetDetail(r *ghttp.Request) {
service.PaymentOrder.GetDetail(r)
}
// Pay 支付订单
func (c *PaymentOrderController) Pay(r *ghttp.Request) {
service.PaymentOrder.Pay(r)
}
// Cancel 取消订单
func (c *PaymentOrderController) Cancel(r *ghttp.Request) {
service.PaymentOrder.Cancel(r)
}

View File

@@ -0,0 +1,49 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// UserCollectController 用户收藏控制器
type UserCollectController struct{}
var UserCollect = &UserCollectController{}
// Add 添加收藏
func (c *UserCollectController) Add(r *ghttp.Request) {
service.UserCollect.Add(r)
}
// Remove 取消收藏
func (c *UserCollectController) Remove(r *ghttp.Request) {
service.UserCollect.Remove(r)
}
// GetList 获取收藏列表
func (c *UserCollectController) GetList(r *ghttp.Request) {
service.NewUserCollectService().GetList(r)
}
// List 获取收藏列表(别名方法)
func (c *UserCollectController) List(r *ghttp.Request) {
c.GetList(r)
}
// Check 检查收藏状态
func (c *UserCollectController) Check(r *ghttp.Request) {
// TODO: 实现检查收藏状态逻辑
r.Response.WriteJson(map[string]interface{}{
"code": 0,
"message": "检查成功",
"data": map[string]interface{}{
"is_collected": false,
},
})
}
// CheckCollect 检查是否已收藏
func (c *UserCollectController) CheckCollect(r *ghttp.Request) {
service.UserCollect.CheckCollect(r)
}

View File

@@ -0,0 +1,80 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// UserWatchHistoryController 用户观看历史控制器
type UserWatchHistoryController struct{}
var UserWatchHistory = &UserWatchHistoryController{}
// Add 添加观看历史
func (c *UserWatchHistoryController) Add(r *ghttp.Request) {
service.NewUserWatchHistoryService().Add(r)
}
// GetList 获取观看历史列表
func (c *UserWatchHistoryController) GetList(r *ghttp.Request) {
service.NewUserWatchHistoryService().GetList(r)
}
// Delete 删除观看历史
func (c *UserWatchHistoryController) Delete(r *ghttp.Request) {
service.NewUserWatchHistoryService().Delete(r)
}
// Clear 清空观看历史
func (c *UserWatchHistoryController) Clear(r *ghttp.Request) {
// 获取用户ID需要实现GetUserIdFromContext函数
userId := service.GetUserIdFromContext(r.Context())
if userId == 0 {
r.Response.WriteJson(map[string]interface{}{
"code": 401,
"message": "请先登录",
})
return
}
err := service.NewUserWatchHistoryService().Clear(r.Context(), &service.UserWatchHistoryClearReq{
UserId: uint(userId),
})
if err != nil {
r.Response.WriteJson(map[string]interface{}{
"code": 1002,
"message": err.Error(),
})
return
}
r.Response.WriteJson(map[string]interface{}{
"code": 0,
"message": "清空成功",
})
}
// GetProgress 获取观看进度
func (c *UserWatchHistoryController) GetProgress(r *ghttp.Request) {
service.NewUserWatchHistoryService().GetProgress(r)
}
// List 获取观看历史列表(别名方法)
func (c *UserWatchHistoryController) List(r *ghttp.Request) {
c.GetList(r)
}
// Get 获取单个观看历史记录
func (c *UserWatchHistoryController) Get(r *ghttp.Request) {
// TODO: 实现获取单个观看历史记录逻辑
r.Response.WriteJson(map[string]interface{}{
"code": 0,
"message": "获取成功",
"data": map[string]interface{}{
"id": 1,
"movie_id": 1,
"progress": 50,
"watch_time": 3600,
},
})
}

View File

@@ -0,0 +1,27 @@
package user
import (
"nl-video-api/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// VipLevelController VIP等级控制器
type VipLevelController struct{}
var VipLevel = &VipLevelController{}
// GetList 获取VIP等级列表
func (c *VipLevelController) GetList(r *ghttp.Request) {
service.VipLevel.GetList(r)
}
// GetAll 获取所有VIP等级
func (c *VipLevelController) GetAll(r *ghttp.Request) {
service.VipLevel.GetAll(r)
}
// GetDetail 获取VIP等级详情
func (c *VipLevelController) GetDetail(r *ghttp.Request) {
service.VipLevel.GetDetail(r)
}