算了,后端我自己写吧
This commit is contained in:
@@ -0,0 +1,345 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"ops/internal/service"
|
||||
"ops/pkg/response"
|
||||
)
|
||||
|
||||
// AuthHandler 用户认证处理器
|
||||
type AuthHandler struct {
|
||||
authService *service.AuthService
|
||||
validate *validator.Validate
|
||||
}
|
||||
|
||||
// LoginRequest 登录请求结构
|
||||
type LoginRequest struct {
|
||||
Name string `json:"name" binding:"required,min=3,max=50"`
|
||||
Password string `json:"password" binding:"required,min=6,max=50"`
|
||||
DeviceID string `json:"deviceID"`
|
||||
IP string `json:"ip"`
|
||||
Remember string `json:"remember"`
|
||||
}
|
||||
|
||||
// LoginResponse 登录响应结构
|
||||
type LoginResponse struct {
|
||||
UserID uint `json:"userID"`
|
||||
Name string `json:"name"`
|
||||
AvatarURL string `json:"avatarURL"`
|
||||
CookieValue string `json:"cookieValue"`
|
||||
CookieExpireDate string `json:"cookieExpireDate"`
|
||||
}
|
||||
|
||||
// RegisterRequest 注册请求结构
|
||||
type RegisterRequest struct {
|
||||
Name string `json:"name" binding:"required,min=3,max=50"`
|
||||
Password string `json:"password" binding:"required,min=6,max=50"`
|
||||
Email string `json:"email" binding:"omitempty,email"`
|
||||
Phone string `json:"phone" binding:"omitempty,len=11"`
|
||||
}
|
||||
|
||||
// RegisterResponse 注册响应结构
|
||||
type RegisterResponse struct {
|
||||
UserID uint `json:"userID"`
|
||||
Name string `json:"name"`
|
||||
CookieValue string `json:"cookieValue"`
|
||||
}
|
||||
|
||||
// ForgotPasswordRequest 忘记密码请求
|
||||
type ForgotPasswordRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Email string `json:"email" binding:"omitempty,email"`
|
||||
Phone string `json:"phone" binding:"omitempty,len=11"`
|
||||
}
|
||||
|
||||
// ResetPasswordRequest 重置密码请求
|
||||
type ResetPasswordRequest struct {
|
||||
Token string `json:"token" binding:"required"`
|
||||
NewPassword string `json:"newPassword" binding:"required,min=6,max=50"`
|
||||
}
|
||||
|
||||
// LogoutRequest 退出登录请求
|
||||
type LogoutRequest struct {
|
||||
CookieValue string `json:"cookieValue" binding:"required"`
|
||||
DeviceID string `json:"deviceID"`
|
||||
}
|
||||
|
||||
// NewAuthHandler 创建认证处理器
|
||||
func NewAuthHandler(db *gorm.DB) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
authService: service.NewAuthService(db),
|
||||
validate: validator.New(),
|
||||
}
|
||||
}
|
||||
|
||||
// UserLogin 用户登录
|
||||
func (h *AuthHandler) UserLogin(c *gin.Context) {
|
||||
var req LoginRequest
|
||||
|
||||
// 绑定和验证请求
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request format")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证请求参数
|
||||
if err := h.validate.Struct(req); err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
user, cookie, err := h.authService.Login(req.Name, req.Password, req.DeviceID, req.IP, req.Remember)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.Error(c, "-5", "User not found")
|
||||
return
|
||||
}
|
||||
if strings.Contains(err.Error(), "password") {
|
||||
response.Error(c, "-42", "Invalid password")
|
||||
return
|
||||
}
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp := LoginResponse{
|
||||
UserID: user.UserID,
|
||||
Name: user.Name,
|
||||
AvatarURL: user.AvatarURL,
|
||||
CookieValue: cookie.Value,
|
||||
CookieExpireDate: cookie.ExpireDate.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
response.Success(c, resp)
|
||||
}
|
||||
|
||||
// UserRegister 用户注册
|
||||
func (h *AuthHandler) UserRegister(c *gin.Context) {
|
||||
var req RegisterRequest
|
||||
|
||||
// 绑定和验证请求
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request format")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证请求参数
|
||||
if err := h.validate.Struct(req); err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
user, cookie, err := h.authService.Register(req.Name, req.Password, req.Email, req.Phone)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate") || strings.Contains(err.Error(), "unique") {
|
||||
response.Error(c, "-4", "Username already exists")
|
||||
return
|
||||
}
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp := RegisterResponse{
|
||||
UserID: user.UserID,
|
||||
Name: user.Name,
|
||||
CookieValue: cookie.Value,
|
||||
}
|
||||
|
||||
response.Success(c, resp)
|
||||
}
|
||||
|
||||
// UserForgotPassword 忘记密码
|
||||
func (h *AuthHandler) UserForgotPassword(c *gin.Context) {
|
||||
var req ForgotPasswordRequest
|
||||
|
||||
// 绑定和验证请求
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request format")
|
||||
return
|
||||
}
|
||||
|
||||
// 至少需要邮箱或手机号之一
|
||||
if req.Email == "" && req.Phone == "" {
|
||||
response.BadRequest(c, "Email or phone number is required")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证请求参数
|
||||
if err := h.validate.Struct(req); err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
token, err := h.authService.ForgotPassword(req.Name, req.Email, req.Phone)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.Error(c, "-5", "User not found")
|
||||
return
|
||||
}
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
response.Success(c, gin.H{
|
||||
"resetToken": token,
|
||||
"message": "Password reset instructions have been sent",
|
||||
})
|
||||
}
|
||||
|
||||
// UserResetPassword 重置密码
|
||||
func (h *AuthHandler) UserResetPassword(c *gin.Context) {
|
||||
var req ResetPasswordRequest
|
||||
|
||||
// 绑定和验证请求
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request format")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证请求参数
|
||||
if err := h.validate.Struct(req); err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
err := h.authService.ResetPassword(req.Token, req.NewPassword)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "invalid") || strings.Contains(err.Error(), "expired") {
|
||||
response.Error(c, "-2", "Reset token is invalid or expired")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.Error(c, "-5", "User not found")
|
||||
return
|
||||
}
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"message": "Password has been reset successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// UserLogout 用户退出登录
|
||||
func (h *AuthHandler) UserLogout(c *gin.Context) {
|
||||
var req LogoutRequest
|
||||
|
||||
// 从认证中间件获取cookie值
|
||||
cookieValue := getCookieFromContext(c)
|
||||
if cookieValue == "" {
|
||||
// 尝试从请求body获取
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "Invalid request format")
|
||||
return
|
||||
}
|
||||
cookieValue = req.CookieValue
|
||||
}
|
||||
|
||||
if cookieValue == "" {
|
||||
response.BadRequest(c, "Cookie value is required")
|
||||
return
|
||||
}
|
||||
|
||||
// 从请求中获取设备ID
|
||||
deviceID := c.GetHeader("X-Device-ID")
|
||||
if deviceID == "" && req.DeviceID != "" {
|
||||
deviceID = req.DeviceID
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
err := h.authService.Logout(cookieValue, deviceID)
|
||||
if err != nil {
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"message": "Logged out successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// UserProfile 获取用户信息
|
||||
func (h *AuthHandler) UserProfile(c *gin.Context) {
|
||||
// 从认证中间件获取用户ID或名称
|
||||
userID := getUserIDFromContext(c)
|
||||
if userID == 0 {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
user, err := h.authService.GetProfile(userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.Error(c, "-5", "User not found")
|
||||
return
|
||||
}
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, user)
|
||||
}
|
||||
|
||||
// UserUpdateProfile 更新用户信息
|
||||
func (h *AuthHandler) UserUpdateProfile(c *gin.Context) {
|
||||
// 从认证中间件获取用户ID
|
||||
userID := getUserIDFromContext(c)
|
||||
if userID == 0 {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 解析更新请求
|
||||
var updateData map[string]interface{}
|
||||
if err := c.ShouldBindJSON(&updateData); err != nil {
|
||||
response.BadRequest(c, "Invalid request format")
|
||||
return
|
||||
}
|
||||
|
||||
// 禁止更新某些字段
|
||||
delete(updateData, "id")
|
||||
delete(updateData, "name")
|
||||
delete(updateData, "password")
|
||||
delete(updateData, "createdAt")
|
||||
|
||||
// 调用服务层
|
||||
user, err := h.authService.UpdateProfile(userID, updateData)
|
||||
if err != nil {
|
||||
response.InternalError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, user)
|
||||
}
|
||||
|
||||
// 辅助函数
|
||||
func getCookieFromContext(c *gin.Context) string {
|
||||
if cookie, exists := c.Get("userCookieValue"); exists && cookie != "" {
|
||||
return cookie.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getUserIDFromContext(c *gin.Context) uint {
|
||||
if userID, exists := c.Get("userID"); exists {
|
||||
if id, ok := userID.(uint); ok {
|
||||
return id
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ops/internal/service"
|
||||
"ops/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type FileHandler struct {
|
||||
service service.FileService
|
||||
}
|
||||
|
||||
func NewFileHandler(db *gorm.DB) *FileHandler {
|
||||
return &FileHandler{
|
||||
service: service.NewFileService(db),
|
||||
}
|
||||
}
|
||||
|
||||
// UploadFile 上传文件
|
||||
// @Summary 上传文件
|
||||
// @Description 上传文件到服务器,支持图片、文档等多种类型
|
||||
// @Tags 文件管理
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param file formData file true "文件内容"
|
||||
// @Param type formData string false "文件类型" default(image)
|
||||
// @Param description formData string false "文件描述"
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 400 {object} response.StandardResponse "参数错误"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Failure 413 {object} response.StandardResponse "文件过大"
|
||||
// @Failure 415 {object} response.StandardResponse "文件类型不支持"
|
||||
// @Failure 500 {object} response.StandardResponse "服务器错误"
|
||||
// @Router /api/v1/files/upload [post]
|
||||
func (h *FileHandler) UploadFile(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取文件类型参数
|
||||
fileType := c.PostForm("type")
|
||||
if fileType == "" {
|
||||
fileType = "image" // 默认类型为图片
|
||||
}
|
||||
|
||||
// 获取文件描述
|
||||
description := c.PostForm("description")
|
||||
|
||||
// 获取上传的文件
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
response.BadRequest(c, "请选择要上传的文件")
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service上传文件
|
||||
uploadResponse, success := h.service.UploadFile(c, userID.(uint), file, fileType, description)
|
||||
if !success {
|
||||
response.BadRequest(c, "文件上传失败,请检查文件格式和大小")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, uploadResponse)
|
||||
}
|
||||
|
||||
// GetFileList 获取文件列表
|
||||
// @Summary 获取文件列表
|
||||
// @Description 获取当前用户上传的文件列表
|
||||
// @Tags 文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param type query string false "文件类型过滤"
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param entries query int false "每页数量" default(20)
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 400 {object} response.StandardResponse "参数错误"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Router /api/v1/files/list [get]
|
||||
func (h *FileHandler) GetFileList(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取查询参数
|
||||
fileType := c.Query("type")
|
||||
page := GetIntParam(c, "page", 1)
|
||||
entries := GetIntParam(c, "entries", 20)
|
||||
|
||||
// 调用Service获取文件列表
|
||||
fileListResponse, success := h.service.GetFileList(userID.(uint), fileType, page, entries)
|
||||
if !success {
|
||||
response.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, fileListResponse)
|
||||
}
|
||||
|
||||
// GetFileByID 获取文件信息
|
||||
// @Summary 获取文件信息
|
||||
// @Description 根据文件ID获取文件详细信息
|
||||
// @Tags 文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param id path int true "文件ID"
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Failure 404 {object} response.StandardResponse "文件不存在"
|
||||
// @Router /api/v1/files/{id} [get]
|
||||
func (h *FileHandler) GetFileByID(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取文件ID
|
||||
fileID := GetUintParam(c, "id")
|
||||
if fileID == 0 {
|
||||
response.BadRequest(c, "文件ID无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service获取文件信息
|
||||
file, success := h.service.GetFileByID(fileID, userID.(uint))
|
||||
if !success {
|
||||
response.Error(c, "-100", "文件不存在或无权限访问")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"file_id": file.ID,
|
||||
"name": file.Name,
|
||||
"sha256": file.Sha256,
|
||||
"mime": file.Mime,
|
||||
"type": file.Type,
|
||||
"size": file.Const, // 注意:这里const字段实际上存储的是使用次数,需要确认实际字段
|
||||
"created_at": file.Date.Format("2006-01-02T15:04:05Z"),
|
||||
"path": file.Path,
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
// @Summary 删除文件
|
||||
// @Description 删除用户上传的文件
|
||||
// @Tags 文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param id path int true "文件ID"
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Failure 404 {object} response.StandardResponse "文件不存在"
|
||||
// @Router /api/v1/files/{id} [delete]
|
||||
func (h *FileHandler) DeleteFile(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取文件ID
|
||||
fileID := GetUintParam(c, "id")
|
||||
if fileID == 0 {
|
||||
response.BadRequest(c, "文件ID无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service删除文件
|
||||
success := h.service.DeleteFile(fileID, userID.(uint))
|
||||
if !success {
|
||||
response.Error(c, "-100", "文件删除失败,文件不存在或无权限")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"message": "文件删除成功"})
|
||||
}
|
||||
|
||||
// DownloadFile 下载文件
|
||||
// @Summary 下载文件
|
||||
// @Description 下载文件内容(直接下载)
|
||||
// @Tags 文件管理
|
||||
// @Accept json
|
||||
// @Produce application/octet-stream
|
||||
// @Param hash path string true "文件SHA256哈希值"
|
||||
// @Success 200 {file} binary "文件内容"
|
||||
// @Failure 404 {object} response.StandardResponse "文件不存在"
|
||||
// @Router /api/v1/files/download/{hash} [get]
|
||||
func (h *FileHandler) DownloadFile(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
if hash == "" {
|
||||
response.BadRequest(c, "文件哈希值无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service下载文件
|
||||
success := h.service.DownloadFile(c, hash, true)
|
||||
if !success {
|
||||
response.Error(c, "-100", "文件不存在")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// GetFile 获取文件(预览)
|
||||
// @Summary 获取文件(预览)
|
||||
// @Description 获取文件内容(浏览器预览)
|
||||
// @Tags 文件管理
|
||||
// @Accept json
|
||||
// @Produce *
|
||||
// @Param hash path string true "文件SHA256哈希值"
|
||||
// @Success 200 {file} binary "文件内容"
|
||||
// @Failure 404 {object} response.StandardResponse "文件不存在"
|
||||
// @Router /api/v1/files/get/{hash} [get]
|
||||
func (h *FileHandler) GetFile(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
if hash == "" {
|
||||
response.BadRequest(c, "文件哈希值无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service获取文件(预览模式)
|
||||
success := h.service.DownloadFile(c, hash, false)
|
||||
if !success {
|
||||
response.Error(c, "-100", "文件不存在")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"ops/internal/service"
|
||||
"ops/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
service service.PurchaseService
|
||||
}
|
||||
|
||||
func NewPurchaseHandler(db *gorm.DB) *PurchaseHandler {
|
||||
return &PurchaseHandler{
|
||||
service: service.NewPurchaseService(db),
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrders 获取采购订单列表
|
||||
// @Summary 获取采购订单列表
|
||||
// @Description 获取用户采购订单列表,支持搜索和分页
|
||||
// @Tags 采购管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param search query string false "搜索关键词"
|
||||
// @Param page query int true "页码" default(1)
|
||||
// @Param entries query int true "每页数量" default(20)
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 400 {object} response.StandardResponse "参数错误"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Failure 500 {object} response.StandardResponse "服务器错误"
|
||||
// @Router /api/v1/purchase/orders [get]
|
||||
func (h *PurchaseHandler) GetOrders(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取查询参数
|
||||
search := c.Query("search")
|
||||
page := GetIntParam(c, "page", 1)
|
||||
entries := GetIntParam(c, "entries", 20)
|
||||
|
||||
// 调用Service
|
||||
result, success := h.service.GetOrders(c, userID.(uint), search, page, entries)
|
||||
if !success {
|
||||
response.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, result)
|
||||
}
|
||||
|
||||
// CreateOrder 创建采购订单
|
||||
// @Summary 创建采购订单
|
||||
// @Description 创建新的采购订单
|
||||
// @Tags 采购管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param request body service.CreateOrderRequest true "订单信息"
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 400 {object} response.StandardResponse "参数错误"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Failure 500 {object} response.StandardResponse "服务器错误"
|
||||
// @Router /api/v1/purchase/orders [post]
|
||||
func (h *PurchaseHandler) CreateOrder(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 解析请求体
|
||||
var request service.CreateOrderRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
var validationErrors []string
|
||||
for _, err := range err.(validator.ValidationErrors) {
|
||||
validationErrors = append(validationErrors, err.Field()+" "+err.Tag())
|
||||
}
|
||||
if len(validationErrors) > 0 {
|
||||
response.BadRequest(c, "参数错误: "+validationErrors[0])
|
||||
} else {
|
||||
response.BadRequest(c, "请求格式错误")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service
|
||||
success := h.service.CreateOrder(c, userID.(uint), request)
|
||||
if !success {
|
||||
response.BadRequest(c, "创建订单失败,请检查数据")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"message": "订单创建成功"})
|
||||
}
|
||||
|
||||
// GetOrderDetails 获取订单详情
|
||||
// @Summary 获取订单详情
|
||||
// @Description 获取采购订单的详细信息
|
||||
// @Tags 采购管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID header string false "用户ID" default("")
|
||||
// @Param id path int true "订单ID"
|
||||
// @Success 200 {object} response.StandardResponse "成功"
|
||||
// @Failure 401 {object} response.StandardResponse "未授权"
|
||||
// @Failure 404 {object} response.StandardResponse "订单不存在"
|
||||
// @Failure 500 {object} response.StandardResponse "服务器错误"
|
||||
// @Router /api/v1/purchase/orders/{id} [get]
|
||||
func (h *PurchaseHandler) GetOrderDetails(c *gin.Context) {
|
||||
// 从上下文中获取用户ID
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取订单ID
|
||||
orderID := GetUintParam(c, "id")
|
||||
if orderID == 0 {
|
||||
response.BadRequest(c, "订单ID无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 调用Service
|
||||
order, costs, err := h.service.GetOrderDetails(orderID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
response.Error(c, "-5", "订单不存在")
|
||||
} else {
|
||||
response.InternalError(c, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查订单所属用户
|
||||
if order.UserID != userID.(uint) {
|
||||
response.Unauthorized(c)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"order": order,
|
||||
"costs": costs,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetIntParam 获取整数参数
|
||||
func GetIntParam(c *gin.Context, key string, defaultValue int) int {
|
||||
value := c.Query(key)
|
||||
if value == "" {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
intValue, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return intValue
|
||||
}
|
||||
|
||||
// GetUintParam 获取uint参数
|
||||
func GetUintParam(c *gin.Context, key string) uint {
|
||||
value := c.Param(key)
|
||||
if value == "" {
|
||||
return 0
|
||||
}
|
||||
|
||||
intValue, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return uint(intValue)
|
||||
}
|
||||
Reference in New Issue
Block a user