| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /*
- * Feedback API List
- * /feedback/submit - POST 提交问题反馈或需求
- * /feedback/history - GET 查询提交历史
- * /feedback/upload - POST 上传附件到 Plane (返回 assetId)
- * /feedback/asset/:id - DELETE 删除已上传的附件
- */
- package controllers
- import (
- "fwh-toolbox-server/dto"
- "fwh-toolbox-server/middleware"
- "fwh-toolbox-server/services"
- "github.com/gofiber/fiber/v2"
- "go.uber.org/zap"
- )
- // 提交反馈
- // /feedback/submit
- func SubmitFeedback(c *fiber.Ctx) error {
- var body dto.FeedbackSubmitDTO
- if err := c.BodyParser(&body); err != nil {
- zap.L().Warn("Invalid request body", zap.String("err", err.Error()))
- return Fail(c, "Invalid request body")
- }
- // 参数校验
- if body.Title == "" {
- return Fail(c, "标题不能为空")
- }
- if body.Type != "bug" && body.Type != "feature" {
- return Fail(c, "类型必须是 bug 或 feature")
- }
- // 从 JWT 中获取用户名
- userName := middleware.AuthGetDisplayName(c)
- result, err := services.SubmitFeedback(body, userName)
- if err != nil {
- return Error(c, err.Error())
- }
- return Success(c, result)
- }
- // 查询提交历史
- // /feedback/history
- func GetFeedbackHistory(c *fiber.Ctx) error {
- // 从 JWT 中获取用户名
- userName := ""
- if name, ok := c.Locals("userName").(string); ok && name != "" {
- userName = name
- }
- result, err := services.GetFeedbackHistory(userName)
- if err != nil {
- return Error(c, err.Error())
- }
- return Success(c, result)
- }
- // 上传附件到 Plane(立即上传,返回 assetId 供后续提交使用)
- // /feedback/upload
- func UploadFeedbackAsset(c *fiber.Ctx) error {
- file, err := c.FormFile("file")
- if err != nil {
- return Fail(c, "请选择文件")
- }
- // 限制文件大小 10MB
- if file.Size > 10*1024*1024 {
- return Fail(c, "文件大小不能超过 10MB")
- }
- // 读取文件内容
- src, err := file.Open()
- if err != nil {
- return Fail(c, "文件读取失败")
- }
- defer src.Close()
- fileData := make([]byte, file.Size)
- if _, err := src.Read(fileData); err != nil {
- return Fail(c, "文件读取失败")
- }
- // 获取 Content-Type
- contentType := file.Header.Get("Content-Type")
- if contentType == "" {
- contentType = "application/octet-stream"
- }
- result, err := services.UploadFeedbackAsset(file.Filename, contentType, file.Size, fileData)
- if err != nil {
- return Error(c, err.Error())
- }
- // 返回 assetId 和 assetUrl
- return Success(c, fiber.Map{
- "assetId": result.AssetID,
- "assetUrl": result.AssetURL,
- })
- }
- // 获取反馈详情(含描述内容)
- // /feedback/detail/:id
- func GetFeedbackDetail(c *fiber.Ctx) error {
- issueId := c.Params("id")
- if issueId == "" {
- return Fail(c, "issue id 不能为空")
- }
- result, err := services.GetFeedbackDetail(issueId)
- if err != nil {
- return Error(c, err.Error())
- }
- return Success(c, result)
- }
- // 代理获取附件文件(从 Plane 下载后转发给前端)
- // /feedback/asset/view/:id
- func ViewFeedbackAsset(c *fiber.Ctx) error {
- assetId := c.Params("id")
- if assetId == "" {
- return Fail(c, "asset id 不能为空")
- }
- contentType, data, err := services.ProxyFeedbackAsset(assetId)
- if err != nil {
- return Error(c, err.Error())
- }
- c.Set("Content-Type", contentType)
- c.Set("Cache-Control", "private, max-age=3600")
- return c.Send(data)
- }
- // 删除已上传的附件
- // /feedback/asset/:id
- func DeleteFeedbackAsset(c *fiber.Ctx) error {
- assetId := c.Params("id")
- if assetId == "" {
- return Fail(c, "asset id 不能为空")
- }
- err := services.DeleteFeedbackAsset(assetId)
- if err != nil {
- return Error(c, err.Error())
- }
- return Success[any](c, nil, "删除成功")
- }
|