first commit

This commit is contained in:
何昌清
2026-03-26 22:13:03 +08:00
parent bbe1faa363
commit a2685f7f1e
51 changed files with 11244 additions and 0 deletions

21
controllers/base_utils.go Normal file
View File

@@ -0,0 +1,21 @@
package controllers
import (
"errors"
"github.com/gin-gonic/gin"
)
func getCode(ctx *gin.Context) (string, error) {
userIDInterface, exists := ctx.Get("code")
if !exists {
return "", errors.New("用户ID不存在")
}
code, ok := userIDInterface.(string)
if !ok {
return "", errors.New("用户ID类型错误")
}
return code, nil
}

View File

@@ -0,0 +1,171 @@
package controllers
import (
"Quincy_admin/config"
"Quincy_admin/schemas"
"Quincy_admin/services"
"Quincy_admin/utils"
"fmt"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
type CommonController struct {
service *services.CommonService
config *config.Config
}
func NewCommonController(service *services.CommonService) *CommonController {
return &CommonController{service: service, config: config.LoadConfig()}
}
// GetLoginLogList 获取系统登录日志
// @Summary 系统登录日志
// @Description 系统登录日志
// @Tags 系统管理
// @Produce json
// @Param role body schemas.LoginLogListRequest true "req"
// @Success 200 {object} utils.Response{data=schemas.LoginLog}
// @Failure 500 {object} utils.Response
// @Router /system/log/login/list [post]
// @Security ApiKeyAuth
func (c *CommonController) GetLoginLogList(ctx *gin.Context) {
var req schemas.LoginLogListRequest
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.GetLoginLogList(&req)
if err != nil {
fmt.Println("获取用户列表时出错:", err)
utils.Error(ctx, http.StatusInternalServerError, "获取日志列表失败")
return
}
response := schemas.LoginLogListResponse{
Item: items,
Total: total,
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
utils.Success(ctx, response)
}
// DownloadLogFile 下载日志文件
// @Summary 下载日志文件
// @Description 下载指定的日志文件内容
// @Tags 系统管理
// @Produce application/octet-stream
// @Param filename query string true "日志文件名"
// @Success 200 {file} file "日志文件内容"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /system/log/download [get]
// @Security ApiKeyAuth
// DownloadLogFile 下载日志文件
func (c *CommonController) DownloadLogFile(ctx *gin.Context) {
filename := ctx.Query("filename")
if filename == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 filename 不能为空")
return
}
// 验证文件名安全性
if strings.Contains(filename, "..") || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
utils.Error(ctx, http.StatusBadRequest, "无效的文件名")
return
}
// 使用 filepath.Join 处理跨平台路径分隔符
filePath := filepath.Join(c.config.Log.Path, filename)
// 检查文件是否存在
if _, err := os.Stat(filePath); os.IsNotExist(err) {
utils.Error(ctx, http.StatusNotFound, "日志文件不存在")
return
}
// 对文件名进行编码以支持中文
encodedFilename := url.QueryEscape(filename)
// 设置响应头
ctx.Header("Content-Description", "File Transfer")
ctx.Header("Content-Transfer-Encoding", "binary")
ctx.Header("Content-Disposition", "attachment; filename*=UTF-8''"+encodedFilename)
ctx.Header("Content-Type", "application/octet-stream")
// 返回文件内容
ctx.File(filePath)
}
// ViewLogFile 查看日志文件内容
// @Summary 查看日志文件内容
// @Description 返回指定日志文件的内容
// @Tags 系统管理
// @Produce json
// @Param filename query string true "日志文件名"
// @Param lines query int false "返回行数默认100行"
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /system/log/view [get]
// @Security ApiKeyAuth
// ViewLogFile 查看日志文件内容
func (c *CommonController) ViewLogFile(ctx *gin.Context) {
filename := ctx.Query("filename")
if filename == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 filename 不能为空")
return
}
linesStr := ctx.Query("lines")
lines := 100 // 默认返回100行
if linesStr != "" {
var err error
lines, err = strconv.Atoi(linesStr)
if err != nil || lines <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 lines 必须是正整数")
return
}
if lines > 1000 {
lines = 1000 // 限制最大行数
}
}
// 验证文件名安全性
if strings.Contains(filename, "..") || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
utils.Error(ctx, http.StatusBadRequest, "无效的文件名")
return
}
// 使用配置文件中的日志目录
f := c.config.Log.Path + "/" + filename
// 读取文件内容
content, err := c.service.ReadLastLines(f, lines)
if err != nil {
if os.IsNotExist(err) {
utils.Error(ctx, http.StatusNotFound, "日志文件不存在")
} else {
utils.Error(ctx, http.StatusInternalServerError, "读取日志文件失败: "+err.Error())
}
return
}
utils.Success(ctx, content)
}

View File

@@ -0,0 +1,263 @@
// Package controllers/pms_controller.go
package controllers
import (
"Quincy_admin/schemas"
"Quincy_admin/services"
"Quincy_admin/utils"
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type CronController struct {
CronService *services.CronService
}
func NewCronController(CronService *services.CronService) *CronController {
return &CronController{CronService: CronService}
}
// GetCronList 定时任务列表
// @Summary 定时任务列表
// @Description 定时任务列表
// @Tags 任务管理
// @Accept json
// @Produce json
// @Param req body schemas.CronListRequest true "定时任务"
// @Success 200 {object} schemas.CronListResponse "定时任务"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/list [post]
// @Security ApiKeyAuth
func (c *CronController) GetCronList(ctx *gin.Context) {
var req schemas.CronListRequest
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.CronService.GetCronList(&req)
if err != nil {
fmt.Println("获取用户列表时出错:", err)
utils.Error(ctx, http.StatusInternalServerError, "获取用户列表失败: "+err.Error())
return
}
response := schemas.CronListResponse{
Item: items,
Total: total,
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
utils.Success(ctx, response)
}
// HandleCron 新增/更新任务
// @Summary 新增/更新任务
// @Description 新增/更新任务
// @Tags 任务管理
// @Accept json
// @Produce json
// @Param req body schemas.CronJobUpdateRequest true "新增/更新任务"
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/hand [post]
// @Security ApiKeyAuth
func (c *CronController) HandleCron(ctx *gin.Context) {
var req schemas.CronJobUpdateRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.Error(ctx, http.StatusBadRequest, "参数错误")
return
}
// 根据ID值判断是新增还是更新
if req.ID > 0 {
// 更新操作
err := c.CronService.UpdateCron(&req)
if err != nil {
utils.Error(ctx, http.StatusInternalServerError, "更新任务失败: "+err.Error())
return
}
utils.Success(ctx, "更新成功")
} else {
// 新增操作
if _, err := c.CronService.AddCron(&req); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "添加任务失败: "+err.Error())
return
}
utils.Success(ctx, "新增成功")
}
}
// StopOrStartCron 启用/停用任务
// @Summary 启用/停用任务
// @Description 启用/停用任务
// @Tags 任务管理
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Param enabled query int false "启用状态(1:启用,0:停用)"
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/{id} [put]
// @Security ApiKeyAuth
func (c *CronController) StopOrStartCron(ctx *gin.Context) {
var idstr = ctx.Param("id")
id, err := strconv.Atoi(idstr)
if err != nil || id <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 id 必须是有效的整数")
return
}
enableStr := ctx.Query("enabled")
if enableStr == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 enabled 不能为空")
return
}
enableValue, err := strconv.Atoi(enableStr)
if err != nil || (enableValue != 0 && enableValue != 1) {
utils.Error(ctx, http.StatusBadRequest, "参数 enabled 必须是0或1")
return
}
// 直接传递整数值到服务层
if err := c.CronService.UpdateCronStatus(id, enableValue); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "更新任务状态失败: "+err.Error())
return
}
if enableValue == 1 {
utils.Success(ctx, "启用成功")
} else {
utils.Success(ctx, "停用成功")
}
}
// DeleteCron 删除定时任务
// @Summary 删除定时任务
// @Description 删除定时任务
// @Tags 任务管理
// @Accept json
// @Produce json
// @Param id path string true "id任务ID"
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/{id} [delete]
// @Security ApiKeyAuth
func (c *CronController) DeleteCron(ctx *gin.Context) {
var idstr = ctx.Param("id")
id, err := strconv.Atoi(idstr)
if err != nil || id <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 id 必须是有效的正整数")
return
}
if err := c.CronService.DeleteCron(id); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "删除任务失败: "+err.Error())
return
}
utils.Success(ctx, "删除成功")
}
// RestartCron 重启定时任务
// @Summary 重启定时任务
// @Description 重启定时任务
// @Tags 任务管理
// @Accept json
// @Produce json
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/restart [get]
// @Security ApiKeyAuth
func (c *CronController) RestartCron(ctx *gin.Context) {
if err := c.CronService.RestartCron(); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "重启调度器失败: "+err.Error())
return
}
utils.Success(ctx, "重启成功")
}
// StopCron 停止所有任务
// @Summary 停止所有任务
// @Description 停止所有任务
// @Tags 任务管理
// @Accept json
// @Produce json
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/stop [get]
// @Security ApiKeyAuth
func (c *CronController) StopCron(ctx *gin.Context) {
if err := c.CronService.StopCron(); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "调度器停止失败: "+err.Error())
return
}
utils.Success(ctx, "停止成功")
}
// GetCronLogList 查看日志运行记录
// @Summary 查看日志运行记录
// @Description 查看日志运行记录
// @Tags 任务管理
// @Accept json
// @Produce json
// @Param req body schemas.CronJobLogListRequest true "req"
// @Success 200 {object} schemas.CronJobLog "res"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /cron/loglist [post]
// @Security ApiKeyAuth
func (c *CronController) GetCronLogList(ctx *gin.Context) {
var req schemas.CronJobLogListRequest
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.CronService.GetCronLogList(&req)
if err != nil {
fmt.Println("获取列表时出错:", err)
utils.Error(ctx, http.StatusInternalServerError, "获取列表失败: "+err.Error())
return
}
response := schemas.CronJobLogListResponse{
Item: items,
Total: total,
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
utils.Success(ctx, response)
}

View File

@@ -0,0 +1,320 @@
// Package controllers/pms_controller.go
package controllers
import (
"Quincy_admin/schemas"
"Quincy_admin/services"
"Quincy_admin/utils"
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type PermissionController struct {
PmsService *services.PermissionService
}
func NewPermissionController(PmsService *services.PermissionService) *PermissionController {
return &PermissionController{PmsService: PmsService}
}
// GetRoutes 侧边菜单权限
// @Summary 侧边菜单权限
// @Description 根据用户Session获取侧边栏菜单权限
// @Tags 权限模块
// @Accept json
// @Produce json
// @Success 200 {object} schemas.MenuItems "菜单信息"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/routes [get]
// @Security ApiKeyAuth
func (c *PermissionController) GetRoutes(ctx *gin.Context) {
// 从请求头获取 X-Access-Token
scode := ctx.GetHeader("X-Access-Token")
if scode == "" {
fmt.Println("无效的用户编码", scode)
utils.Fail(ctx, http.StatusBadRequest, "无效的用户编码")
return
}
roleIDInterface, exists := ctx.Get("role_id")
if !exists {
utils.Error(ctx, http.StatusUnauthorized, "权限校验错误用户ID不存在")
ctx.Abort()
return
}
roleID, ok := roleIDInterface.(int)
if !ok {
utils.Error(ctx, http.StatusUnauthorized, "权限校验错误用户ID类型错误")
ctx.Abort()
return
}
items, err := c.PmsService.GetRoutesByID(roleID)
if err != nil {
fmt.Println("获取路由权限失败", err)
utils.Fail(ctx, http.StatusNotFound, "获取失败")
return
}
utils.Success(ctx, items.Children)
}
// GetMenuList 获取菜单列表
// @Summary 获取菜单列表
// @Description 获取管理后台菜单列表
// @Tags 权限模块
// @Accept json
// @Produce json
// @Param role body schemas.MenuListRequest true "req"
// @Success 200 {object} schemas.MenuItems "菜单信息"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/menus [post]
// @Security ApiKeyAuth
func (c *PermissionController) GetMenuList(ctx *gin.Context) {
var req schemas.MenuListRequest
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.PmsService.GetMenuList(req.PageIndex, req.PageSize)
if err != nil {
utils.Error(ctx, http.StatusInternalServerError, err.Error())
return
}
response := schemas.MenuListResponse{
Item: items,
Total: total,
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
utils.Success(ctx, response)
}
// UpdateMenuStatus 启用停用菜单
// @Summary 启用停用菜单
// @Description 启用停用菜单
// @Tags 权限模块
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Param status query int false "启用状态(1:启用,0:停用)"
// @Success 200 {object} utils.Response{data=string}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/menus/{id} [put]
// @Security ApiKeyAuth
func (c *PermissionController) UpdateMenuStatus(ctx *gin.Context) {
var idstr = ctx.Param("id")
id, err := strconv.Atoi(idstr)
if err != nil || id <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 id 必须是有效的整数")
return
}
statusStr := ctx.Query("status")
if statusStr == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 status 不能为空")
return
}
statusValue, err := strconv.Atoi(statusStr)
if err != nil || (statusValue != 0 && statusValue != 1) {
utils.Error(ctx, http.StatusBadRequest, "参数 status 必须是0或1")
return
}
// 直接传递整数值到服务层
if err := c.PmsService.UpdateMenuStatus(id, statusValue); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "更新任务状态失败: "+err.Error())
return
}
if statusValue == 1 {
utils.Success(ctx, "启用成功")
} else {
utils.Success(ctx, "停用成功")
}
}
// GetPermission 获取权限列表
// @Summary 获取权限列表
// @Description 根据用户Session和权限type获取权限列表
// @Tags 权限模块
// @Accept json
// @Produce json
// @Param type query string false "all-全部 button-按钮route-路由menu-菜单api-接口"
// @Success 200 {object} []string "权限列表"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/permission [get]
// @Security ApiKeyAuth
func (c *PermissionController) GetPermission(ctx *gin.Context) {
// 获取角色 ID
roleIDInterface, exists := ctx.Get("role_id")
if !exists {
utils.Error(ctx, http.StatusUnauthorized, "权限校验错误用户ID不存在")
ctx.Abort()
return
}
roleID, ok := roleIDInterface.(int)
if !ok {
utils.Error(ctx, http.StatusUnauthorized, "权限校验错误用户ID类型错误")
ctx.Abort()
return
}
typeStr := ctx.Query("type")
if typeStr == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 type 不能为空")
return
}
items, err := c.PmsService.GetPermission(roleID, typeStr)
if err != nil {
fmt.Println("获取路由权限失败", err)
utils.Fail(ctx, http.StatusNotFound, "获取失败")
return
}
utils.Success(ctx, items)
}
// GetAllPermission 获取所有权限
// @Summary 获取所有权限
// @Description 获取所有权限
// @Tags 权限模块
// @Accept json
// @Produce json
// @Success 200 {object} schemas.PermissionItems "权限列表"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/permission/all [get]
// @Security ApiKeyAuth
// @Security ApiKeyAuth
func (c *PermissionController) GetAllPermission(ctx *gin.Context) {
items, err := c.PmsService.GetAllPermission()
if err != nil {
fmt.Println("获取路由权限失败", err)
utils.Fail(ctx, http.StatusNotFound, "获取失败")
return
}
// 返回树形结构,包含所有层级的 children
utils.Success(ctx, items.Children)
}
// GetRolePermission 获取角色权限
// @Summary 获取角色权限
// @Description 获取角色权限
// @Tags 权限模块
// @Accept json
// @Produce json
// @param role_id query int true "角色ID"
// @Param type query string false "all-全部 button-按钮route-路由menu-菜单api-接口"
// @Success 200 {object} utils.Response{data=[]int} "权限列表"
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/permission/role [get]
// @Security ApiKeyAuth
func (c *PermissionController) GetRolePermission(ctx *gin.Context) {
// 获取角色 ID
var roleIDStr = ctx.Query("role_id")
roleID, err := strconv.Atoi(roleIDStr)
if err != nil {
utils.Error(ctx, http.StatusBadRequest, "参数 role_id 错误")
return
}
typeStr := ctx.Query("type")
if typeStr == "" {
utils.Error(ctx, http.StatusBadRequest, "参数 type 不能为空")
return
}
items, err := c.PmsService.GetRolePermission(roleID, typeStr)
if err != nil {
fmt.Println("获取路由权限失败", err)
utils.Fail(ctx, http.StatusNotFound, "获取失败")
return
}
utils.Success(ctx, items)
}
// AssignPermission 分配角色权限
// @Summary 分配角色权限
// @Description 为指定角色分配权限
// @Tags 权限模块
// @Accept json
// @Produce json
// @Param role_id path int true "角色ID"
// @Param permission_ids query []int true "权限ID数组"
// @Success 200 {object} utils.Response "权限分配成功"
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /pms/permission/assign/{role_id} [put]
// @Security ApiKeyAuth
func (c *PermissionController) AssignPermission(ctx *gin.Context) {
// 从 path 参数获取角色 ID
roleIDStr := ctx.Param("role_id")
roleID, err := strconv.Atoi(roleIDStr)
if err != nil || roleID <= 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 role_id 必须是有效的正整数")
return
}
if roleID == 1 {
utils.Error(ctx, http.StatusForbidden, "无权修改超级管理员角色")
return
}
// 从请求体解析权限ID数组
var permissionIDs []int
if err := ctx.ShouldBindJSON(&permissionIDs); err != nil {
utils.Error(ctx, http.StatusBadRequest, "参数格式错误: "+err.Error())
return
}
// 验证权限ID数组不为空
if len(permissionIDs) == 0 {
utils.Error(ctx, http.StatusBadRequest, "参数 permission_ids 不能为空")
return
}
// 验证每个权限ID的有效性
for _, id := range permissionIDs {
if id <= 0 {
utils.Error(ctx, http.StatusBadRequest, fmt.Sprintf("权限ID '%d' 必须是有效的正整数", id))
return
}
}
// 调用服务层处理权限分配
if err := c.PmsService.AssignPermission(roleID, permissionIDs); err != nil {
utils.Error(ctx, http.StatusInternalServerError, "权限分配失败: "+err.Error())
return
}
utils.Success(ctx, "权限分配成功")
}

View File

@@ -0,0 +1,508 @@
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, "创建成功")
}
}