package handler import ( "errors" "kra/internal/service" "net/http" "net/url" "strings" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type Export struct { service *service.ExportService } func NewExport(service *service.ExportService) *Export { return &Export{service: service} } func exportParams(values url.Values) (map[string]string, error) { out := map[string]string{} nested, err := url.ParseQuery(values.Get("params")) if err != nil { return nil, err } for key, items := range nested { if len(items) > 0 { out[key] = items[0] } } return out, nil } func exportIssueParams(values url.Values, blank bool) (map[string]string, error) { params, err := exportParams(values) if err != nil && blank { return map[string]string{}, nil } return params, err } func (h *Export) Create(c *gin.Context) { var req service.ExportTemplateRequest if err := c.ShouldBindJSON(&req); err != nil { Fail(c, err.Error()) return } if req.Name == "" { Fail(c, "Name值不能为空") return } if err := h.service.CreateRequest(c.Request.Context(), &req); err != nil { Fail(c, "创建失败") return } Write(c, CodeSuccess, gin.H{}, "创建成功") } func (h *Export) Update(c *gin.Context) { var req service.ExportTemplateRequest if err := c.ShouldBindJSON(&req); err != nil { Fail(c, err.Error()) return } if req.Name == "" { Fail(c, "Name值不能为空") return } if err := h.service.UpdateRequest(c.Request.Context(), &req); err != nil { Fail(c, "更新失败") return } Write(c, CodeSuccess, gin.H{}, "更新成功") } func (h *Export) Delete(c *gin.Context) { var req service.IDRequest if err := c.ShouldBindJSON(&req); err != nil { Fail(c, err.Error()) return } // Deleting an empty model is rejected by GORM's global-update guard in the // reference endpoint. Preserve the same externally visible failure. if req.ID == 0 { Fail(c, "删除失败") return } if err := h.service.Delete(c.Request.Context(), []uint{req.ID}); err != nil { Fail(c, "删除失败") return } Write(c, CodeSuccess, gin.H{}, "删除成功") } func (h *Export) DeleteMany(c *gin.Context) { var req service.IDsRequest if err := c.ShouldBindJSON(&req); err != nil { Fail(c, err.Error()) return } if err := h.service.Delete(c.Request.Context(), req.IDs); err != nil { Fail(c, "批量删除失败") return } Write(c, CodeSuccess, gin.H{}, "批量删除成功") } func (h *Export) Find(c *gin.Context) { var req service.ExportTemplateRequest if err := c.ShouldBindQuery(&req); err != nil { Fail(c, err.Error()) return } item, err := h.service.Template(c.Request.Context(), req.ID, "") if err != nil { Fail(c, "查询失败") return } OKWithData(c, gin.H{"resysExportTemplate": item}) } func (h *Export) List(c *gin.Context) { p, size, err := page(c) if err != nil { Fail(c, err.Error()) return } start, startErr := parseTime(c.Query("startCreatedAt")) end, endErr := parseTime(c.Query("endCreatedAt")) if startErr != nil || endErr != nil { 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 { Fail(c, "获取失败") return } Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: p, PageSize: size}, "获取成功") } func (h *Export) Preview(c *gin.Context) { templateID := c.Query("templateID") if templateID == "" { Fail(c, "模板ID不能为空") return } params, _ := exportParams(c.Request.URL.Query()) sql, err := h.service.Preview(c.Request.Context(), templateID, params) if err != nil { Fail(c, "获取失败") return } OKWithData(c, gin.H{"sql": sql}) } func (h *Export) Issue(blank bool) gin.HandlerFunc { return func(c *gin.Context) { templateID := c.Query("templateID") if templateID == "" { Fail(c, "模板ID不能为空") return } params, err := exportIssueParams(c.Request.URL.Query(), blank) if err != nil { Fail(c, "解析 params 参数失败") return } token, err := h.service.IssueToken(c.Request.Context(), templateID, params, blank) if err != nil { Fail(c, "导出令牌创建失败") return } path := "/sysExportTemplate/exportExcelByToken?token=" + token if blank { path = "/sysExportTemplate/exportTemplateByToken?token=" + token } OKWithData(c, path) } } func (h *Export) Import(c *gin.Context) { templateID := c.Query("templateID") if templateID == "" { Fail(c, "模板ID不能为空") return } file, err := c.FormFile("file") if err != nil { Fail(c, "文件获取失败") return } opened, err := file.Open() if err != nil { Fail(c, "读取文件失败") return } defer opened.Close() if err = h.service.Import(c.Request.Context(), templateID, opened); err != nil { Fail(c, err.Error()) return } Write(c, CodeSuccess, gin.H{}, "导入成功") } func (h *Export) Download(expectBlank bool) gin.HandlerFunc { return func(c *gin.Context) { token := c.Query("token") if token == "" { Fail(c, "导出token不能为空") return } value, err := h.service.ConsumeToken(c.Request.Context(), token, expectBlank) if err != nil { switch { case errors.Is(err, service.ErrExportTokenMalformed): Fail(c, "解析导出参数失败") case errors.Is(err, service.ErrExportTokenType): Fail(c, "token类型错误") default: Fail(c, "导出token无效或已过期") } 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 { Fail(c, "获取失败") return } if expectBlank { name = strings.TrimSuffix(name, "_template.xlsx") + "模板.xlsx" } else { name = strings.TrimSuffix(name, ".xlsx") + strings.ReplaceAll(uuid.NewString(), "-", "")[:6] + ".xlsx" } c.Header("Content-Disposition", "attachment; filename="+name) c.Header("success", "true") c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", data) } }