Files
Quincy_admin/controllers/user_controller.go
2026-03-26 22:13:03 +08:00

509 lines
14 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controllers
import (
"Quincy_admin/config"
"Quincy_admin/schemas"
"Quincy_admin/services"
"Quincy_admin/utils"
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type UserController struct {
service *services.UserService
config *config.Config
}
func NewUserController(service *services.UserService) *UserController {
return &UserController{service: service, config: config.LoadConfig()}
}
// Create 创建用户
// @Summary 创建用户
// @Description 创建用户
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param user body schemas.CreateUser true "用户信息"
// @Success 200 {object} utils.Response{data=schemas.UserResponse}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /user/register [post]
// @Security ApiKeyAuth
func (c *UserController) Create(ctx *gin.Context) {
var user schemas.CreateUser
if err := ctx.ShouldBindJSON(&user); err != nil {
utils.Error(ctx, http.StatusBadRequest, "无效的请求数据,JSON解析错误")
return
}
// 检查邮箱是否重复
email, err := c.service.IsEmailExists(user.Email)
if err != nil {
utils.Error(ctx, http.StatusInternalServerError, err.Error())
return
}
if email > 0 {
utils.Error(ctx, http.StatusBadRequest, "邮箱已存在")
return
}
if err := c.service.CreateUser(&user); err != nil {
utils.Error(ctx, http.StatusInternalServerError, err.Error())
return
}
user.Password = ""
response := map[string]string{
"sessioncode": user.SessionCode,
}
utils.Success(ctx, response)
}
// GetByID 获取用户信息
// @Summary 获取用户信息
// @Description 获取用户信息
// @Tags 用户管理
// @Produce json
// @Success 200 {object} utils.Response{data=schemas.UserInfo}
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Router /user/getinfo [get]
// @Security ApiKeyAuth
func (c *UserController) GetByID(ctx *gin.Context) {
scode, err := getCode(ctx)
if err != nil {
utils.Error(ctx, http.StatusUnauthorized, "用户ID不存在")
return
}
if scode == "" {
utils.Error(ctx, http.StatusBadRequest, "无效的用户编码")
return
}
user, err := c.service.GetUserByID(scode)
if err != nil {
utils.Error(ctx, http.StatusNotFound, "用户不存在")
return
}
if user.RoleCode == 0 {
utils.Fail(ctx, http.StatusForbidden, "未分配权限")
return
}
// 不返回密码等敏感信息
user.Password = ""
utils.Success(ctx, user)
}
// Update 更新用户信息
// @Summary 更新用户信息
// @Description 更新用户信息
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param user body schemas.UpdateUser true "用户信息"
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /user/update [put]
// @Security ApiKeyAuth
func (c *UserController) Update(ctx *gin.Context) {
var user schemas.UpdateUser
if err := ctx.ShouldBindJSON(&user); err != nil {
utils.Error(ctx, http.StatusBadRequest, "无效的请求数据")
return
}
// 防止修改超级管理员账户ID=1
if user.ID == 1 {
utils.Error(ctx, http.StatusForbidden, "无权限修改超级管理员账户")
return
}
if _, err := c.service.UpdateUser(&user); err != nil {
utils.Error(ctx, http.StatusInternalServerError, err.Error())
return
}
user.Password = ""
utils.Success(ctx, user.ID)
}
// UpdateStatus 禁用/启用用户
// @Summary 禁用/启用用户
// @Description 禁用/启用用户
// @Tags 用户管理
// @Param id path string true "用户ID"
// @Param status query int false "启用状态(1:启用,0:停用)"
// @Success 200 {object} utils.Response
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /user/{id} [put]
// @Security ApiKeyAuth
func (c *UserController) UpdateStatus(ctx *gin.Context) {
idstr := ctx.Param("id")
id, err := strconv.Atoi(idstr)
if err != nil || id <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 id 必须是有效的整数")
return
}
// 防止修改超级管理员账户ID=1
if id == 1 {
utils.Error(ctx, http.StatusForbidden, "无权限修改超级管理员账户")
return
}
status := ctx.Query("status")
if status == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 status 不能为空")
return
}
statusValue, err := strconv.Atoi(status)
if err != nil || (statusValue != 0 && statusValue != 1) {
utils.Error(ctx, http.StatusBadRequest, "参数 status 必须是0或1")
return
}
// 直接传递整数值到服务层
if err := c.service.UpdateStatus(id, statusValue); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "操作失败: "+err.Error())
return
}
if statusValue == 1 {
utils.Success(ctx, "启用成功")
} else {
utils.Success(ctx, "停用成功")
}
}
// Login 用户登录
// @Summary 用户登录
// @Description 用户登录验证
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param login body schemas.LoginRequest true "req"
// @Success 200 {object} utils.Response{data=schemas.UserResponse}
// @Failure 400 {object} utils.Response
// @Failure 401 {object} utils.Response
// @Failure 403 {object} utils.Response
// @Router /user/login [post]
func (c *UserController) Login(ctx *gin.Context) {
var loginReq schemas.LoginRequest
if err := ctx.ShouldBindJSON(&loginReq); err != nil {
utils.Fail(ctx, http.StatusBadRequest, "无效的登录数据")
return
}
user, err := c.service.GetUserByUsername(loginReq.Username)
if err != nil {
// 记录失败登录日志
err := c.service.RecordLoginLog(0, loginReq.Username, ctx.ClientIP(), ctx.Request.UserAgent(), 0, "用户不存在")
if err != nil {
return
}
utils.Fail(ctx, http.StatusUnauthorized, "用户不存在")
return
}
// 更新最后登录时间
if err := c.service.UpdateLastLoginTime(user.SessionCode); err != nil {
// 记录失败登录日志
err := c.service.RecordLoginLog(0, loginReq.Username, ctx.ClientIP(), ctx.Request.UserAgent(), 0, "系统错误")
if err != nil {
return
}
utils.Fail(ctx, http.StatusInternalServerError, "系统错误")
return
}
if user.Status == schemas.UserStatusDisabled {
// 记录失败登录日志
err := c.service.RecordLoginLog(user.ID, user.Username, ctx.ClientIP(), ctx.Request.UserAgent(), 0, "用户已被锁定")
if err != nil {
return
}
utils.Fail(ctx, http.StatusForbidden, "用户已被锁定")
return
}
if user.RoleCode == 0 {
// 记录失败登录日志
err := c.service.RecordLoginLog(user.ID, user.Username, ctx.ClientIP(), ctx.Request.UserAgent(), 0, "未分配权限")
if err != nil {
return
}
utils.Fail(ctx, http.StatusForbidden, "未分配权限")
return
}
if !c.service.VerifyPassword(loginReq.Password, user.Password) {
// 记录失败登录日志
err := c.service.RecordLoginLog(user.ID, user.Username, ctx.ClientIP(), ctx.Request.UserAgent(), 0, "密码错误")
if err != nil {
return
}
utils.Fail(ctx, http.StatusUnauthorized, "密码错误")
return
}
// 记录成功登录日志
err = c.service.RecordLoginLog(user.ID, user.Username, ctx.ClientIP(), ctx.Request.UserAgent(), 1, "")
if err != nil {
return
}
user.Password = ""
//err = c.service.StoreLoginSession(user.SessionCode, user, 24*time.Hour)
//if err != nil {
// utils.Error(ctx, http.StatusInternalServerError, "登录失败")
// return
//}
// 生成 JWT token
token, err := utils.GenerateToken(user.ID, user.Username, user.SessionCode, user.RoleCode)
if err != nil {
utils.Error(ctx, http.StatusInternalServerError, "生成令牌失败")
return
}
// 返回 token 和用户信息
response := map[string]interface{}{
"Authorization": token,
}
utils.Success(ctx, response)
}
// UserList 获取用户列表
// @Summary 获取用户列表
// @Description 获取用户列表
// @Tags 用户管理
// @Produce json
// @Param user body schemas.UserListRequest true "请求体"
// @Success 200 {object} utils.Response{data=schemas.UserListResponse}
// @Failure 500 {object} utils.Response
// @Router /user/list [post]
// @Security ApiKeyAuth
func (c *UserController) UserList(ctx *gin.Context) {
var req schemas.UserListRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.Error(ctx, http.StatusBadRequest, "参数错误")
return
}
if req.PageIndex <= 0 || req.PageSize <= 0 || req.PageSize > 100 {
utils.Error(ctx, http.StatusBadRequest, "分页参数错误")
return
}
users, total, err := c.service.GetUserList(&req)
if err != nil {
fmt.Println("获取用户列表时出错:", err)
utils.Error(ctx, http.StatusInternalServerError, "获取用户列表失败")
return
}
// 清除用户密码信息
for _, user := range users {
user.Password = ""
}
response := schemas.UserListResponse{
Item: users,
Total: total,
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
utils.Success(ctx, response)
}
// UserRoleList 获取角色列表
// @Summary 获取角色列表
// @Description 获取角色列表
// @Tags 用户管理
// @Produce json
// @Param role body schemas.RoleListRequest true "req"
// @Success 200 {object} utils.Response{data=schemas.RoleResponseList}
// @Failure 500 {object} utils.Response
// @Router /user/rolelist [post]
// @Security ApiKeyAuth
func (c *UserController) UserRoleList(ctx *gin.Context) {
var req schemas.RoleListRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.Error(ctx, http.StatusBadRequest, "参数错误")
return
}
if req.PageIndex <= 0 || req.PageSize <= 0 || req.PageSize > 100 {
utils.Error(ctx, http.StatusBadRequest, "分页参数错误")
return
}
items, total, err := c.service.GetRoleList(&req)
if err != nil {
fmt.Println("获取用户列表时出错:", err)
utils.Error(ctx, http.StatusInternalServerError, "获取用户列表失败")
return
}
response := schemas.RoleListResponse{
Item: items,
Total: total,
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
utils.Success(ctx, response)
}
// AssignRole 用户角色分配
// @Summary 用户角色分配
// @Description 用户角色分配
// @Tags 用户管理
// @Param user_id query string true "用户ID"
// @Param role_id query int false "角色ID"
// @Success 200 {object} utils.Response
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /user/assign [put]
// @Security ApiKeyAuth
func (c *UserController) AssignRole(ctx *gin.Context) {
userId := ctx.Query("user_id")
userIdValue, err := strconv.Atoi(userId)
if err != nil || userIdValue <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 user_id 必须是有效的整数")
return
}
if userIdValue == 1 {
utils.Error(ctx, http.StatusForbidden, "无权限修改超级管理员账户")
return
}
roleId := ctx.Query("role_id")
roleIdValue, err := strconv.Atoi(roleId)
if err != nil || roleIdValue <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 role_id 必须是有效的整数")
return
}
if roleIdValue == 1 {
utils.Error(ctx, http.StatusForbidden, "禁止分配超级管理员权限")
return
}
// 直接传递整数值到服务层
if err := c.service.AssignRole(userIdValue, roleIdValue); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "操作失败: "+err.Error())
return
}
utils.Success(ctx, "")
}
// UpdateRoleStatus 禁用/启用角色
// @Summary 禁用/启用角色
// @Description 禁用/启用角色
// @Tags 用户管理
// @Param id path string true "角色ID"
// @Param status query int false "启用状态(1:启用,0:停用)"
// @Success 200 {object} utils.Response
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /user/role/{id} [put]
// @Security ApiKeyAuth
func (c *UserController) UpdateRoleStatus(ctx *gin.Context) {
idstr := ctx.Param("id")
id, err := strconv.Atoi(idstr)
if err != nil || id <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 id 必须是有效的整数")
return
}
// 防止修改超级管理员账户ID=1
if id == 1 {
utils.Error(ctx, http.StatusForbidden, "无权限修改超级管理员账户")
return
}
status := ctx.Query("status")
if status == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 status 不能为空")
return
}
statusValue, err := strconv.Atoi(status)
if err != nil || (statusValue != 0 && statusValue != 1) {
utils.Error(ctx, http.StatusBadRequest, "参数 status 必须是0或1")
return
}
// 直接传递整数值到服务层
if err := c.service.UpdateRoleStatus(id, statusValue); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "操作失败: "+err.Error())
return
}
if statusValue == 1 {
utils.Success(ctx, "启用成功")
} else {
utils.Success(ctx, "停用成功")
}
}
// CreateRole 创建角色
// @Summary 创建角色
// @Description 创建角色
// @Tags 用户管理
// @Produce json
// @Param role body schemas.CreateRole true "req"
// @Success 200 {object} utils.Response
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /user/role [post]
// @Security ApiKeyAuth
func (c *UserController) CreateRole(ctx *gin.Context) {
var req schemas.CreateRole
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.Error(ctx, http.StatusBadRequest, "参数错误")
return
}
if req.ID == 1 {
utils.Error(ctx, http.StatusForbidden, "无权限修改超级管理员账户")
return
}
// 判断ID是否传入传了更新没传新增
if req.ID > 0 {
// 更新角色
if err := c.service.UpdateRole(&req); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "更新失败: "+err.Error())
return
}
utils.Success(ctx, "更新成功")
} else {
// 新增角色
if err := c.service.CreateRole(&req); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "创建失败: "+err.Error())
return
}
utils.Success(ctx, "创建成功")
}
}