371 lines
9.9 KiB
Go
371 lines
9.9 KiB
Go
|
|
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,
|
||
|
|
})
|
||
|
|
}
|