package app import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "io" "net/url" "os" "path/filepath" "strconv" "strings" "time" "verification-platform-backend/internal/database" "verification-platform-backend/internal/middleware" "verification-platform-backend/internal/model" "verification-platform-backend/internal/service" "verification-platform-backend/pkg/response" "github.com/gin-gonic/gin" ) func SetupCloudRoutes(r *gin.RouterGroup) { r.GET("/constants", handleAppGetConstants) r.GET("/constants/:key", handleAppGetConstantByKey) r.GET("/constants/:key/download", handleAppDownloadConstant) r.GET("/variables", handleAppGetVariables) r.GET("/variables/:key", handleAppGetVariableByKey) r.GET("/variables/:key/download", handleAppDownloadVariable) r.POST("/variables/:key/upload", handleAppUploadVariableBinary) r.POST("/variables", handleAppUpdateVariables) r.POST("/variables/:key/records", handleAppCreateVariableRecord) r.GET("/variables/:key/records", handleAppGetVariableRecords) r.DELETE("/variables/:key/records/:record_id", handleAppDeleteVariableRecord) r.POST("/call-function", handleAppCallFunction) } func handleAppGetConstants(c *gin.Context) { appKey := c.Param("appKey") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端常量") return } var constants []model.CloudConstant if err := database.DB.Where("user_id = ? AND app_id = ? AND status = ?", app.UserID, app.ID, "active").Find(&constants).Error; err != nil { response.Error(c, 500, "获取云端常量失败") return } result := make(map[string]interface{}) for _, constant := range constants { if constant.VarType == "binary" { result[constant.Key] = gin.H{ "type": "binary", "value": "/api/v1/app/" + appKey + "/constants/" + constant.Key + "/download", "file_name": constant.OriginalName, "file_size": constant.FileSize, "md5": constant.FileMD5, "mime_type": constant.MimeType, } } else { result[constant.Key] = gin.H{ "type": constant.VarType, "value": constant.Value, } } } response.Success(c, result) } func handleAppGetConstantByKey(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端常量") return } var constant model.CloudConstant if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&constant).Error; err != nil { response.Error(c, 404, "云端常量不存在") return } if constant.VarType == "binary" { response.Success(c, gin.H{ "key": constant.Key, "type": "binary", "value": "/api/v1/app/" + appKey + "/constants/" + constant.Key + "/download", "file_name": constant.OriginalName, "file_size": constant.FileSize, "md5": constant.FileMD5, "mime_type": constant.MimeType, }) } else { response.Success(c, gin.H{ "key": constant.Key, "type": constant.VarType, "value": constant.Value, }) } } func handleAppDownloadConstant(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端常量") return } var constant model.CloudConstant if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&constant).Error; err != nil { response.Error(c, 404, "云端常量不存在") return } if constant.VarType != "binary" || constant.FilePath == "" { response.Error(c, 400, "该常量不是文件类型") return } filePath := constant.FilePath if strings.HasPrefix(filePath, "/") { filePath = filePath[1:] } if _, err := os.Stat(filePath); os.IsNotExist(err) { response.Error(c, 404, "文件不存在") return } encodedFilename := url.QueryEscape(constant.OriginalName) c.Header("Content-Description", "File Transfer") c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename*=UTF-8''"+encodedFilename) c.Header("Content-Transfer-Encoding", "binary") c.Header("Expires", "0") c.Header("Cache-Control", "must-revalidate") c.Header("Pragma", "public") c.FileAttachment(filePath, constant.OriginalName) } func handleAppGetVariables(c *gin.Context) { appKey := c.Param("appKey") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variables []model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND status = ?", app.UserID, app.ID, "active").Find(&variables).Error; err != nil { response.Error(c, 500, "获取云端变量失败") return } var userVariables []model.UserVariable if err := database.DB.Where("user_id = ? AND app_id = ?", userID, app.ID).Find(&userVariables).Error; err != nil { response.Error(c, 500, "获取用户变量失败") return } userVarMap := make(map[string]model.UserVariable) for _, uv := range userVariables { userVarMap[uv.VarName] = uv } result := make(map[string]interface{}) for _, v := range variables { if v.VarType == "binary" { if v.Scope == "user" { if uv, ok := userVarMap[v.Key]; ok && uv.FilePath != "" { result[v.Key] = gin.H{ "type": "binary", "value": "/api/v1/app/" + appKey + "/variables/" + v.Key + "/download", "file_name": uv.OriginalName, "file_size": uv.FileSize, "md5": uv.FileMD5, "mime_type": uv.MimeType, } } else { result[v.Key] = gin.H{ "type": "binary", "value": "/api/v1/app/" + appKey + "/variables/" + v.Key + "/download", "file_name": v.OriginalName, "file_size": v.FileSize, "md5": v.FileMD5, "mime_type": v.MimeType, } } } else { result[v.Key] = gin.H{ "type": "binary", "value": "/api/v1/app/" + appKey + "/variables/" + v.Key + "/download", "file_name": v.OriginalName, "file_size": v.FileSize, "md5": v.FileMD5, "mime_type": v.MimeType, } } } else { if v.Scope == "app" { result[v.Key] = gin.H{ "type": v.VarType, "value": v.DefaultValue, } } else { value := v.DefaultValue if uv, ok := userVarMap[v.Key]; ok { value = uv.VarValue } result[v.Key] = gin.H{ "type": v.VarType, "value": value, } } } } response.Success(c, result) } func handleAppGetVariableByKey(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variable model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&variable).Error; err != nil { response.Error(c, 404, "云端变量不存在") return } if variable.VarType == "binary" { if variable.Scope == "user" { var userVar model.UserVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).First(&userVar).Error; err == nil && userVar.FilePath != "" { response.Success(c, gin.H{ "key": variable.Key, "type": "binary", "value": "/api/v1/app/" + appKey + "/variables/" + variable.Key + "/download", "file_name": userVar.OriginalName, "file_size": userVar.FileSize, "md5": userVar.FileMD5, "mime_type": userVar.MimeType, }) return } } response.Success(c, gin.H{ "key": variable.Key, "type": "binary", "value": "/api/v1/app/" + appKey + "/variables/" + variable.Key + "/download", "file_name": variable.OriginalName, "file_size": variable.FileSize, "md5": variable.FileMD5, "mime_type": variable.MimeType, }) return } if variable.Scope == "app" { response.Success(c, gin.H{ "key": variable.Key, "type": variable.VarType, "value": variable.DefaultValue, }) return } var userVar model.UserVariable value := variable.DefaultValue if err := database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).First(&userVar).Error; err == nil { value = userVar.VarValue } response.Success(c, gin.H{ "key": variable.Key, "type": variable.VarType, "value": value, }) } func handleAppDownloadVariable(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variable model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&variable).Error; err != nil { response.Error(c, 404, "云端变量不存在") return } if variable.VarType != "binary" { response.Error(c, 400, "该变量不是二进制类型") return } var filePath string var originalName string if variable.Scope == "user" { var userVar model.UserVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).First(&userVar).Error; err == nil && userVar.FilePath != "" { filePath = userVar.FilePath originalName = userVar.OriginalName } else { filePath = variable.FilePath originalName = variable.OriginalName } } else { filePath = variable.FilePath originalName = variable.OriginalName } if filePath == "" { response.Error(c, 400, "该变量没有关联文件") return } if strings.HasPrefix(filePath, "/") { filePath = filePath[1:] } if _, err := os.Stat(filePath); os.IsNotExist(err) { response.Error(c, 404, "文件不存在") return } encodedFilename := url.QueryEscape(originalName) c.Header("Content-Description", "File Transfer") c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename*=UTF-8''"+encodedFilename) c.Header("Content-Transfer-Encoding", "binary") c.Header("Expires", "0") c.Header("Cache-Control", "must-revalidate") c.Header("Pragma", "public") c.FileAttachment(filePath, originalName) } func handleAppUpdateVariables(c *gin.Context) { appKey := c.Param("appKey") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var req struct { Variables map[string]string `json:"variables"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, 400, "参数错误") return } var variables []model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ?", app.UserID, app.ID).Find(&variables).Error; err != nil { response.Error(c, 500, "获取云端变量失败") return } varMap := make(map[string]model.CloudVariable) for _, v := range variables { varMap[v.Key] = v } for key, value := range req.Variables { variable, exists := varMap[key] if !exists { continue } if variable.Scope == "app" { variable.DefaultValue = value database.DB.Save(&variable) } else { var userVar model.UserVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).First(&userVar).Error; err != nil { userVar = model.UserVariable{ UserID: userID.(uint), AppID: app.ID, VarName: key, VarValue: value, VarType: variable.VarType, } database.DB.Create(&userVar) } else { userVar.VarValue = value database.DB.Save(&userVar) } } } response.Success(c, gin.H{ "message": "更新成功", }) } func handleAppUploadVariableBinary(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variable model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&variable).Error; err != nil { response.Error(c, 404, "云端变量不存在") return } if variable.VarType != "binary" { response.Error(c, 400, "该变量不是二进制类型") return } if variable.WritePermission != "user" { response.Error(c, 403, "该变量不允许用户写入") return } file, header, err := c.Request.FormFile("file") if err != nil { response.Error(c, 400, "请选择要上传的文件") return } defer file.Close() var developer model.User if err := database.DB.First(&developer, app.UserID).Error; err != nil { response.Error(c, 500, "获取开发者信息失败") return } if developer.CurrentPackageID != nil { var permission model.PackagePermission if err := database.DB.Where("package_id = ?", developer.CurrentPackageID).First(&permission).Error; err == nil { maxStorageBytes := int64(permission.MaxStorage) * 1024 * 1024 if developer.StorageUsed+header.Size > maxStorageBytes { usedMB := float64(developer.StorageUsed) / 1024 / 1024 maxMB := float64(permission.MaxStorage) response.Error(c, 403, fmt.Sprintf("存储空间不足,已使用 %.2f MB / %.2f MB", usedMB, maxMB)) return } } } uploadDir := "uploads/cloud-files" if err := os.MkdirAll(uploadDir, 0755); err != nil { response.Error(c, 500, "创建上传目录失败") return } ext := filepath.Ext(header.Filename) filename := fmt.Sprintf("%d_%d_%d%s", app.UserID, userID, time.Now().UnixNano(), ext) filePath := filepath.Join(uploadDir, filename) dst, err := os.Create(filePath) if err != nil { response.Error(c, 500, "创建文件失败") return } defer dst.Close() hash := md5.New() multiWriter := io.MultiWriter(dst, hash) if _, err := io.Copy(multiWriter, file); err != nil { response.Error(c, 500, "保存文件失败") return } fileMD5 := hex.EncodeToString(hash.Sum(nil)) fileURL := "/uploads/cloud-files/" + filename mimeType := header.Header.Get("Content-Type") if mimeType == "" { mimeType = "application/octet-stream" } if variable.Scope == "app" { if variable.FilePath != "" && variable.FileSize > 0 { oldFilePath := variable.FilePath if strings.HasPrefix(oldFilePath, "/") { oldFilePath = oldFilePath[1:] } os.Remove(oldFilePath) if err := middleware.UpdateStorageUsed(app.UserID, variable.FileSize, "delete"); err != nil { fmt.Printf("更新存储使用量失败: %v\n", err) } } variable.DefaultValue = fileURL variable.FilePath = fileURL variable.FileSize = header.Size variable.MimeType = mimeType variable.OriginalName = header.Filename variable.FileMD5 = fileMD5 database.DB.Save(&variable) } else { var userVar model.UserVariable existingFile := false if err := database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).First(&userVar).Error; err == nil { if userVar.FilePath != "" && userVar.FileSize > 0 { existingFile = true } } userVar = model.UserVariable{ UserID: userID.(uint), AppID: app.ID, VarName: key, VarValue: fileURL, VarType: "binary", FilePath: fileURL, FileSize: header.Size, MimeType: mimeType, OriginalName: header.Filename, FileMD5: fileMD5, } if existingFile { var oldVar model.UserVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).First(&oldVar).Error; err == nil { if oldVar.FilePath != "" && oldVar.FileSize > 0 { oldFilePath := oldVar.FilePath if strings.HasPrefix(oldFilePath, "/") { oldFilePath = oldFilePath[1:] } os.Remove(oldFilePath) if err := middleware.UpdateStorageUsed(app.UserID, oldVar.FileSize, "delete"); err != nil { fmt.Printf("更新存储使用量失败: %v\n", err) } } } } database.DB.Where("user_id = ? AND app_id = ? AND var_name = ?", userID, app.ID, key).Assign(userVar).FirstOrCreate(&userVar) } if err := middleware.UpdateStorageUsed(app.UserID, header.Size, "upload"); err != nil { fmt.Printf("更新存储使用量失败: %v\n", err) } response.Success(c, gin.H{ "message": "上传成功", "file_url": fileURL, "file_size": header.Size, "mime_type": mimeType, "original_name": header.Filename, "download_url": "/api/v1/app/" + appKey + "/variables/" + key + "/download", }) } func handleAppCallFunction(c *gin.Context) { appKey := c.Param("appKey") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var req struct { UserID uint `json:"user_id"` Name string `json:"name"` Params map[string]interface{} `json:"params"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, 400, "参数错误") return } response.Success(c, gin.H{ "result": nil, }) } func handleAppCreateVariableRecord(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variable model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&variable).Error; err != nil { response.Error(c, 404, "云端变量不存在") return } if variable.VarType != "stream" { response.Error(c, 400, "该变量不是记录类型") return } if variable.WritePermission != "user" && variable.WritePermission != "app_user" { response.Error(c, 403, "该变量不允许应用用户写入") return } var req map[string]interface{} if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, 400, "参数错误") return } dataBytes, err := json.Marshal(req) if err != nil { response.Error(c, 500, "序列化数据失败") return } record := model.CloudVariableRecord{ CloudVariableID: variable.ID, Data: string(dataBytes), } if variable.Scope == "user" { appUserID := userID.(uint) record.AppUserID = &appUserID } if err := database.DB.Create(&record).Error; err != nil { response.Error(c, 500, "创建记录失败") return } if variable.MaxRecords > 0 { var total int64 database.DB.Model(&model.CloudVariableRecord{}).Where("cloud_variable_id = ?", variable.ID).Count(&total) if int(total) > variable.MaxRecords { deleteCount := int(total) - variable.MaxRecords var oldRecords []model.CloudVariableRecord database.DB.Where("cloud_variable_id = ?", variable.ID). Order("created_at ASC"). Limit(deleteCount). Find(&oldRecords) for _, r := range oldRecords { database.DB.Delete(&r) } } } response.Success(c, gin.H{ "id": record.ID, "created_at": record.CreatedAt, }) } func handleAppGetVariableRecords(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variable model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&variable).Error; err != nil { response.Error(c, 404, "云端变量不存在") return } if variable.VarType != "stream" { response.Error(c, 400, "该变量不是记录类型") return } 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 } var total int64 query := database.DB.Model(&model.CloudVariableRecord{}).Where("cloud_variable_id = ?", variable.ID) if variable.Scope == "user" { query = query.Where("app_user_id = ?", userID) } query.Count(&total) var records []model.CloudVariableRecord offset := (page - 1) * pageSize if err := query.Order("created_at DESC").Limit(pageSize).Offset(offset).Find(&records).Error; err != nil { response.Error(c, 500, "获取记录失败") return } result := make([]gin.H, len(records)) for i, r := range records { var data map[string]interface{} json.Unmarshal([]byte(r.Data), &data) result[i] = gin.H{ "id": r.ID, "data": data, "created_at": r.CreatedAt, } } response.Success(c, gin.H{ "records": result, "total": total, "page": page, "page_size": pageSize, "total_pages": (total + int64(pageSize) - 1) / int64(pageSize), }) } func handleAppDeleteVariableRecord(c *gin.Context) { appKey := c.Param("appKey") key := c.Param("key") recordID := c.Param("record_id") userID, _ := c.Get("user_id") var app model.Application if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil { response.Error(c, 404, "应用不存在") return } if service.GetApplicationDisabledStatus(app.ID) { response.Error(c, 403, "该应用已被禁用") return } var appUser model.AppUser if err := database.DB.Where("id = ? AND application_id = ?", userID, app.ID).First(&appUser).Error; err != nil { response.Error(c, 403, "无权访问该应用的云端变量") return } var variable model.CloudVariable if err := database.DB.Where("user_id = ? AND app_id = ? AND key = ? AND status = ?", app.UserID, app.ID, key, "active").First(&variable).Error; err != nil { response.Error(c, 404, "云端变量不存在") return } if variable.VarType != "stream" { response.Error(c, 400, "该变量不是记录类型") return } var record model.CloudVariableRecord query := database.DB.Where("id = ? AND cloud_variable_id = ?", recordID, variable.ID) if variable.Scope == "user" { query = query.Where("app_user_id = ?", userID) } if err := query.First(&record).Error; err != nil { response.Error(c, 404, "记录不存在") return } if err := database.DB.Delete(&record).Error; err != nil { response.Error(c, 500, "删除记录失败") return } response.Success(c, nil) }