package handler import ( "encoding/json" "net/http" "net/url" "strconv" "strings" "time" "kra/internal/server/httpx" "kra/internal/service" "kra/internal/service/dto" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type Export struct { system *service.SystemService service *service.ExportService } func NewExport(system *service.SystemService, service *service.ExportService) *Export { return &Export{system: system, service: service} } type exportToken struct { TemplateID string `json:"templateID"` Params map[string]string `json:"params"` Blank bool `json:"blank"` } func exportParams(values url.Values) map[string]string { out := map[string]string{} nested, _ := url.ParseQuery(values.Get("params")) for key, items := range nested { if len(items) > 0 { out[key] = items[0] } } for key, items := range values { if key != "params" && len(items) > 0 { out[key] = items[0] } } return out } func (h *Export) Create(c *gin.Context) { var req dto.ExportTemplateRequest if c.ShouldBindJSON(&req) != nil || req.Name == "" || req.TemplateID == "" { httpx.Fail(c, "参数错误") return } if err := h.service.CreateRequest(c.Request.Context(), &req); err != nil { httpx.Fail(c, "创建失败:"+err.Error()) return } httpx.OK(c) } func (h *Export) Update(c *gin.Context) { var req dto.ExportTemplateRequest if c.ShouldBindJSON(&req) != nil || req.ID == 0 { httpx.Fail(c, "参数错误") return } if err := h.service.UpdateRequest(c.Request.Context(), &req); err != nil { httpx.Fail(c, "更新失败:"+err.Error()) return } httpx.OK(c) } func (h *Export) Delete(c *gin.Context) { var req dto.IDRequest if c.ShouldBindJSON(&req) != nil { httpx.Fail(c, "参数错误") return } if err := h.service.Delete(c.Request.Context(), []uint{req.ID}); err != nil { httpx.Fail(c, "删除失败") return } httpx.OK(c) } func (h *Export) DeleteMany(c *gin.Context) { var req dto.IDsRequest if c.ShouldBindJSON(&req) != nil { httpx.Fail(c, "参数错误") return } if err := h.service.Delete(c.Request.Context(), req.IDs); err != nil { httpx.Fail(c, "删除失败") return } httpx.OK(c) } func (h *Export) Find(c *gin.Context) { id, _ := strconv.ParseUint(c.Query("ID"), 10, 64) item, err := h.service.Template(c.Request.Context(), uint(id), "") if err != nil { httpx.Fail(c, "查询失败") return } httpx.Write(c, httpx.CodeSuccess, gin.H{"resysExportTemplate": item}, "查询成功") } func (h *Export) List(c *gin.Context) { p, size := page(c) start, startErr := parseTime(c.Query("startCreatedAt")) end, endErr := parseTime(c.Query("endCreatedAt")) if startErr != nil || endErr != nil { httpx.Fail(c, "参数错误") return } items, total, err := h.service.TemplatesFilter(c.Request.Context(), p, size, c.Query("name"), c.Query("tableName"), c.Query("templateID"), start, end) if err != nil { httpx.Fail(c, "获取失败") return } httpx.Write(c, httpx.CodeSuccess, httpx.PageResult{List: items, Total: total, Page: p, PageSize: size}, "获取成功") } func (h *Export) Preview(c *gin.Context) { sql, err := h.service.Preview(c.Request.Context(), c.Query("templateID"), exportParams(c.Request.URL.Query())) if err != nil { httpx.Fail(c, "预览失败:"+err.Error()) return } httpx.Write(c, httpx.CodeSuccess, gin.H{"sql": sql}, "获取成功") } func (h *Export) Issue(blank bool) gin.HandlerFunc { return func(c *gin.Context) { templateID := c.Query("templateID") if templateID == "" { httpx.Fail(c, "模板ID不能为空") return } token := strings.ReplaceAll(uuid.NewString(), "-", "") raw, _ := json.Marshal(exportToken{TemplateID: templateID, Params: exportParams(c.Request.URL.Query()), Blank: blank}) if err := h.system.CacheSet(c.Request.Context(), "export:"+token, string(raw), 5*time.Minute); err != nil { httpx.Fail(c, "导出令牌创建失败") return } httpx.Write(c, httpx.CodeSuccess, gin.H{"token": token}, "获取成功") } } func (h *Export) Import(c *gin.Context) { file, err := c.FormFile("file") if err != nil { httpx.Fail(c, "请选择导入文件") return } opened, err := file.Open() if err != nil { httpx.Fail(c, "读取文件失败") return } defer opened.Close() templateID := c.PostForm("templateID") if templateID == "" { templateID = c.Query("templateID") } if err = h.service.Import(c.Request.Context(), templateID, opened); err != nil { httpx.Fail(c, err.Error()) return } httpx.OK(c) } func (h *Export) Download(expectBlank bool) gin.HandlerFunc { return func(c *gin.Context) { token := c.Query("token") raw, ok, err := h.system.CacheGet(c.Request.Context(), "export:"+token) if err != nil || !ok { httpx.Fail(c, "导出令牌无效或已过期") return } _ = h.system.CacheDelete(c.Request.Context(), "export:"+token) var value exportToken if json.Unmarshal([]byte(raw), &value) != nil || value.Blank != expectBlank { httpx.Fail(c, "导出令牌无效") return } var data []byte var name string if expectBlank { data, name, err = h.service.ExportBlankTemplate(c.Request.Context(), value.TemplateID) } else { data, name, err = h.service.Export(c.Request.Context(), value.TemplateID, value.Params) } if err != nil { httpx.Fail(c, "导出失败:"+err.Error()) return } c.Header("Content-Disposition", "attachment; filename*=UTF-8''"+url.QueryEscape(name)) c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", data) } }