package handlers import ( "log" "strconv" "github.com/gin-gonic/gin" "github.com/niangaodev/art-code/models" "github.com/niangaodev/art-code/repositories" "github.com/niangaodev/art-code/utils" ) // AdminUploadAttachment 上传附件 func AdminUploadAttachment(c *gin.Context) { // 获取文件 file, err := c.FormFile("file") if err != nil { utils.Error(c, 400, "No file uploaded") return } // 获取分类ID(可选) categoryIDStr := c.PostForm("categoryId") var categoryID *uint if categoryIDStr != "" { if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil { idUint := uint(id) categoryID = &idUint } } // 获取存储类型 storageType := c.DefaultPostForm("storageType", "local") // 打开文件 src, err := file.Open() if err != nil { utils.Error(c, 500, "Failed to open file") return } defer src.Close() // 获取OSS配置 var ossConfig *models.OSSConfig if storageType != "local" { ossConfig, err = repositories.GetActiveOSSConfig(storageType) if err != nil || ossConfig == nil { utils.Error(c, 400, "OSS config not found or not active") return } } // 创建OSS配置对象 config := &utils.OSSConfig{ StorageType: storageType, } if ossConfig != nil { // 解密AccessKey和SecretKey accessKey, err := utils.DecryptAES(ossConfig.AccessKey) if err != nil { log.Printf("Failed to decrypt access key: %v", err) utils.Error(c, 500, "Failed to decrypt OSS credentials") return } secretKey, err := utils.DecryptAES(ossConfig.SecretKey) if err != nil { log.Printf("Failed to decrypt secret key: %v", err) utils.Error(c, 500, "Failed to decrypt OSS credentials") return } config.AccessKey = accessKey config.SecretKey = secretKey config.Bucket = ossConfig.Bucket config.Region = ossConfig.Region config.Domain = ossConfig.Domain } // 获取上传器 uploader, err := utils.GetOSSUploader(config) if err != nil { utils.Error(c, 500, err.Error()) return } // 上传文件 filePath, fileURL, err := uploader.Upload(src, file.Filename, file.Size) if err != nil { utils.Error(c, 500, "Failed to upload file: "+err.Error()) return } // 获取文件类型 fileType := utils.GetFileType(file.Header.Get("Content-Type")) // 创建附件记录 attachment := &models.Attachment{ CategoryID: categoryID, OriginalName: file.Filename, StoredName: file.Filename, FilePath: filePath, FileURL: fileURL, FileSize: file.Size, FileType: fileType, MimeType: file.Header.Get("Content-Type"), StorageType: storageType, } if ossConfig != nil { ossConfigID := ossConfig.ID attachment.OSSConfigID = &ossConfigID } if err := repositories.CreateAttachment(attachment); err != nil { // 如果数据库保存失败,尝试删除已上传的文件 uploader.Delete(filePath) utils.ServerError(c, err) return } utils.SuccessWithMsg(c, "File uploaded successfully", attachment) } // AdminGetAttachments 获取附件列表 func AdminGetAttachments(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20")) categoryIDStr := c.Query("categoryId") fileType := c.Query("fileType") var categoryID *uint if categoryIDStr != "" { if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil { idUint := uint(id) categoryID = &idUint } } attachments, total, err := repositories.GetAttachments(page, pageSize, categoryID, fileType) if err != nil { utils.ServerError(c, err) return } res := gin.H{ "list": attachments, "total": total, "page": page, "size": pageSize, } utils.Success(c, res) } // AdminDeleteAttachment 删除附件 func AdminDeleteAttachment(c *gin.Context) { idStr := c.Param("id") var id uint if _, err := strconv.ParseUint(idStr, 10, 32); err != nil { utils.Error(c, 400, "Invalid attachment ID") return } // 获取附件信息 attachment, err := repositories.GetAttachmentByID(id) if err != nil || attachment == nil { utils.Error(c, 404, "Attachment not found") return } // 获取OSS配置并删除文件 if attachment.StorageType != "" { var ossConfig *models.OSSConfig if attachment.OSSConfigID != nil { ossConfig, err = repositories.GetOSSConfigByID(*attachment.OSSConfigID) } else { ossConfig, err = repositories.GetActiveOSSConfig(attachment.StorageType) } if err == nil && ossConfig != nil { config := &utils.OSSConfig{ StorageType: attachment.StorageType, } // 解密密钥 if accessKey, err := utils.DecryptAES(ossConfig.AccessKey); err == nil { config.AccessKey = accessKey } if secretKey, err := utils.DecryptAES(ossConfig.SecretKey); err == nil { config.SecretKey = secretKey } config.Bucket = ossConfig.Bucket config.Region = ossConfig.Region config.Domain = ossConfig.Domain uploader, err := utils.GetOSSUploader(config) if err == nil { uploader.Delete(attachment.FilePath) } } } // 删除数据库记录 if err := repositories.DeleteAttachment(id); err != nil { utils.ServerError(c, err) return } utils.SuccessWithMsg(c, "Attachment deleted successfully", nil) } // AdminGetAttachmentCategories 获取附件分类列表 func AdminGetAttachmentCategories(c *gin.Context) { categories, err := repositories.GetAttachmentCategories() if err != nil { utils.ServerError(c, err) return } utils.Success(c, categories) } // AdminCreateAttachmentCategory 创建附件分类 func AdminCreateAttachmentCategory(c *gin.Context) { var category models.AttachmentCategory if err := c.ShouldBindJSON(&category); err != nil { utils.Error(c, 400, "Invalid request") return } if err := repositories.CreateAttachmentCategory(&category); err != nil { utils.ServerError(c, err) return } utils.SuccessWithMsg(c, "Category created successfully", category) } // AdminUpdateAttachmentCategory 更新附件分类 func AdminUpdateAttachmentCategory(c *gin.Context) { idStr := c.Param("id") var id uint if _, err := strconv.ParseUint(idStr, 10, 32); err != nil { utils.Error(c, 400, "Invalid category ID") return } var category models.AttachmentCategory if err := c.ShouldBindJSON(&category); err != nil { utils.Error(c, 400, "Invalid request") return } category.ID = id if err := repositories.UpdateAttachmentCategory(&category); err != nil { utils.ServerError(c, err) return } utils.SuccessWithMsg(c, "Category updated successfully", nil) } // AdminDeleteAttachmentCategory 删除附件分类 func AdminDeleteAttachmentCategory(c *gin.Context) { idStr := c.Param("id") var id uint if _, err := strconv.ParseUint(idStr, 10, 32); err != nil { utils.Error(c, 400, "Invalid category ID") return } if err := repositories.DeleteAttachmentCategory(id); err != nil { utils.ServerError(c, err) return } utils.SuccessWithMsg(c, "Category deleted successfully", nil) } // AdminGetOSSConfigs 获取OSS配置列表 func AdminGetOSSConfigs(c *gin.Context) { configs, err := repositories.GetOSSConfigs() if err != nil { utils.ServerError(c, err) return } // 不返回加密的密钥 for i := range configs { configs[i].AccessKey = "***" configs[i].SecretKey = "***" } utils.Success(c, configs) } // AdminCreateOSSConfig 创建OSS配置 func AdminCreateOSSConfig(c *gin.Context) { var req struct { Name string `json:"name" binding:"required"` StorageType string `json:"storageType" binding:"required"` AccessKey string `json:"accessKey" binding:"required"` SecretKey string `json:"secretKey" binding:"required"` Bucket string `json:"bucket"` Region string `json:"region"` Domain string `json:"domain"` IsActive int `json:"isActive"` } if err := c.ShouldBindJSON(&req); err != nil { utils.Error(c, 400, "Invalid request") return } // 加密密钥 encryptedAccessKey, err := utils.EncryptAES(req.AccessKey) if err != nil { utils.Error(c, 500, "Failed to encrypt access key") return } encryptedSecretKey, err := utils.EncryptAES(req.SecretKey) if err != nil { utils.Error(c, 500, "Failed to encrypt secret key") return } ossConfig := &models.OSSConfig{ Name: req.Name, StorageType: req.StorageType, AccessKey: encryptedAccessKey, SecretKey: encryptedSecretKey, Bucket: req.Bucket, Region: req.Region, Domain: req.Domain, IsActive: req.IsActive, } if err := repositories.CreateOSSConfig(ossConfig); err != nil { utils.ServerError(c, err) return } // 不返回加密的密钥 ossConfig.AccessKey = "***" ossConfig.SecretKey = "***" utils.SuccessWithMsg(c, "OSS config created successfully", ossConfig) } // AdminUpdateOSSConfig 更新OSS配置 func AdminUpdateOSSConfig(c *gin.Context) { idStr := c.Param("id") var id uint if _, err := strconv.ParseUint(idStr, 10, 32); err != nil { utils.Error(c, 400, "Invalid OSS config ID") return } var req struct { Name string `json:"name"` StorageType string `json:"storageType"` AccessKey string `json:"accessKey"` SecretKey string `json:"secretKey"` Bucket string `json:"bucket"` Region string `json:"region"` Domain string `json:"domain"` IsActive int `json:"isActive"` } if err := c.ShouldBindJSON(&req); err != nil { utils.Error(c, 400, "Invalid request") return } // 获取现有配置 existingConfig, err := repositories.GetOSSConfigByID(id) if err != nil || existingConfig == nil { utils.Error(c, 404, "OSS config not found") return } // 更新字段 if req.Name != "" { existingConfig.Name = req.Name } if req.StorageType != "" { existingConfig.StorageType = req.StorageType } if req.AccessKey != "" && req.AccessKey != "***" { encryptedAccessKey, err := utils.EncryptAES(req.AccessKey) if err != nil { utils.Error(c, 500, "Failed to encrypt access key") return } existingConfig.AccessKey = encryptedAccessKey } if req.SecretKey != "" && req.SecretKey != "***" { encryptedSecretKey, err := utils.EncryptAES(req.SecretKey) if err != nil { utils.Error(c, 500, "Failed to encrypt secret key") return } existingConfig.SecretKey = encryptedSecretKey } if req.Bucket != "" { existingConfig.Bucket = req.Bucket } if req.Region != "" { existingConfig.Region = req.Region } if req.Domain != "" { existingConfig.Domain = req.Domain } existingConfig.IsActive = req.IsActive if err := repositories.UpdateOSSConfig(existingConfig); err != nil { utils.ServerError(c, err) return } // 不返回加密的密钥 existingConfig.AccessKey = "***" existingConfig.SecretKey = "***" utils.SuccessWithMsg(c, "OSS config updated successfully", existingConfig) } // AdminDeleteOSSConfig 删除OSS配置 func AdminDeleteOSSConfig(c *gin.Context) { idStr := c.Param("id") var id uint if _, err := strconv.ParseUint(idStr, 10, 32); err != nil { utils.Error(c, 400, "Invalid OSS config ID") return } if err := repositories.DeleteOSSConfig(id); err != nil { utils.ServerError(c, err) return } utils.SuccessWithMsg(c, "OSS config deleted successfully", nil) }