2025-12-03 11:00:47 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* package api
|
|
|
|
|
|
* 作用:附件管理相关API处理器
|
|
|
|
|
|
*/
|
|
|
|
|
|
package api
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-12-05 16:21:43 +08:00
|
|
|
|
"path/filepath"
|
2025-12-03 11:00:47 +08:00
|
|
|
|
"strconv"
|
2025-12-05 16:21:43 +08:00
|
|
|
|
"strings"
|
2025-12-03 11:00:47 +08:00
|
|
|
|
"xk-websocket-v2/internal/model"
|
|
|
|
|
|
"xk-websocket-v2/internal/service"
|
|
|
|
|
|
"xk-websocket-v2/internal/utils"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* UploadAttachmentHandler
|
|
|
|
|
|
* 功能:上传附件
|
|
|
|
|
|
* 路径:POST /api/attachments/upload
|
|
|
|
|
|
*/
|
|
|
|
|
|
func UploadAttachmentHandler(c *gin.Context) {
|
|
|
|
|
|
userID, _ := c.Get("user_id")
|
|
|
|
|
|
|
|
|
|
|
|
// 获取文件
|
|
|
|
|
|
file, err := c.FormFile("file")
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.BadRequest(c, "文件上传失败: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取文件类型
|
|
|
|
|
|
fileType := c.PostForm("type")
|
|
|
|
|
|
if fileType == "" {
|
|
|
|
|
|
// 根据文件扩展名推断类型
|
2025-12-05 16:21:43 +08:00
|
|
|
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
|
|
|
|
|
if ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".webp" {
|
2025-12-03 11:00:47 +08:00
|
|
|
|
fileType = "image"
|
2025-12-05 16:21:43 +08:00
|
|
|
|
} else if ext == ".mp4" || ext == ".avi" || ext == ".mov" || ext == ".wmv" || ext == ".flv" || ext == ".mkv" {
|
2025-12-03 11:00:47 +08:00
|
|
|
|
fileType = "video"
|
2025-12-05 16:21:43 +08:00
|
|
|
|
} else if ext == ".mp3" || ext == ".wav" || ext == ".m4a" || ext == ".webm" || ext == ".ogg" || ext == ".aac" {
|
|
|
|
|
|
fileType = "audio"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
fileType = "file"
|
2025-12-03 11:00:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证文件类型
|
2025-12-05 16:21:43 +08:00
|
|
|
|
if fileType != "image" && fileType != "video" && fileType != "audio" && fileType != "file" {
|
|
|
|
|
|
utils.BadRequest(c, "文件类型必须是image、video、audio或file")
|
2025-12-03 11:00:47 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证文件大小
|
|
|
|
|
|
if fileType == "image" && file.Size > model.MaxImageSize {
|
|
|
|
|
|
utils.BadRequest(c, "图片大小不能超过10MB")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileType == "video" && file.Size > model.MaxVideoSize {
|
|
|
|
|
|
utils.BadRequest(c, "视频大小不能超过500MB")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-12-05 16:21:43 +08:00
|
|
|
|
if fileType == "audio" && file.Size > model.MaxAudioSize {
|
|
|
|
|
|
utils.BadRequest(c, "音频大小不能超过50MB")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileType == "file" && file.Size > model.MaxFileSize {
|
|
|
|
|
|
utils.BadRequest(c, "文件大小不能超过100MB")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-12-03 11:00:47 +08:00
|
|
|
|
|
|
|
|
|
|
// 打开文件
|
|
|
|
|
|
src, err := file.Open()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.BadRequest(c, "打开文件失败: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
defer src.Close()
|
|
|
|
|
|
|
|
|
|
|
|
// 上传文件
|
|
|
|
|
|
attachment, err := service.AttachmentSvc.UploadFile(
|
|
|
|
|
|
userID.(string),
|
|
|
|
|
|
file.Filename,
|
|
|
|
|
|
fileType,
|
|
|
|
|
|
file.Size,
|
|
|
|
|
|
src,
|
|
|
|
|
|
)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.BadRequest(c, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
utils.SuccessWithData(c, attachment, "上传成功")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* GetAttachmentHandler
|
|
|
|
|
|
* 功能:获取附件信息
|
|
|
|
|
|
* 路径:GET /api/attachments/:id
|
|
|
|
|
|
*/
|
|
|
|
|
|
func GetAttachmentHandler(c *gin.Context) {
|
|
|
|
|
|
attachmentID, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
|
|
|
|
|
|
|
|
|
|
|
attachment, err := service.AttachmentSvc.GetAttachment(uint(attachmentID))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.NotFound(c, "附件不存在")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
utils.SuccessWithData(c, attachment, "获取成功")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* DeleteAttachmentHandler
|
|
|
|
|
|
* 功能:删除附件(仅上传者可删除)
|
|
|
|
|
|
* 路径:DELETE /api/attachments/:id
|
|
|
|
|
|
*/
|
|
|
|
|
|
func DeleteAttachmentHandler(c *gin.Context) {
|
|
|
|
|
|
userID, _ := c.Get("user_id")
|
|
|
|
|
|
attachmentID, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
|
|
|
|
|
|
|
|
|
|
|
if err := service.AttachmentSvc.DeleteAttachment(uint(attachmentID), userID.(string)); err != nil {
|
|
|
|
|
|
utils.BadRequest(c, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
utils.Success(c, "附件已删除")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* GetAttachmentsHandler
|
|
|
|
|
|
* 功能:获取附件列表
|
|
|
|
|
|
* 路径:GET /api/attachments
|
|
|
|
|
|
*/
|
|
|
|
|
|
func GetAttachmentsHandler(c *gin.Context) {
|
|
|
|
|
|
userID, _ := c.Get("user_id")
|
|
|
|
|
|
fileType := c.Query("type")
|
|
|
|
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
|
|
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
|
|
|
|
|
|
|
|
|
|
|
if page < 1 {
|
|
|
|
|
|
page = 1
|
|
|
|
|
|
}
|
|
|
|
|
|
if pageSize < 1 || pageSize > 100 {
|
|
|
|
|
|
pageSize = 20
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
attachments, total, err := service.AttachmentSvc.GetUserAttachments(userID.(string), fileType, page, pageSize)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.InternalError(c, "查询失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 确保返回空数组而不是null
|
|
|
|
|
|
if attachments == nil {
|
|
|
|
|
|
attachments = []model.Attachment{}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
utils.SuccessWithData(c, gin.H{
|
|
|
|
|
|
"data": attachments,
|
|
|
|
|
|
"total": total,
|
|
|
|
|
|
"page": page,
|
|
|
|
|
|
"size": pageSize,
|
|
|
|
|
|
}, "获取成功")
|
|
|
|
|
|
}
|
|
|
|
|
|
|