183 lines
4.7 KiB
Go
183 lines
4.7 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"kenaito-notebook-server/models"
|
|
"kenaito-notebook-server/services"
|
|
)
|
|
|
|
type ExportHandler struct {
|
|
db *services.Database
|
|
exportSvc *services.ExportService
|
|
}
|
|
|
|
func NewExportHandler(db *services.Database, exportSvc *services.ExportService) *ExportHandler {
|
|
return &ExportHandler{db: db, exportSvc: exportSvc}
|
|
}
|
|
|
|
func (h *ExportHandler) ExportHTML(c *gin.Context) {
|
|
var req struct {
|
|
Title string `json:"title" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
outputPath, err := h.getTempExportPath(req.Title, ".html")
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
if err := h.exportSvc.ExportHTML(req.Title, req.Content, outputPath); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"filePath": outputPath})
|
|
}
|
|
|
|
func (h *ExportHandler) ExportMarkdown(c *gin.Context) {
|
|
var req struct {
|
|
Title string `json:"title" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
outputPath, err := h.getTempExportPath(req.Title, ".md")
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
if err := h.exportSvc.ExportMarkdown(req.Title, req.Content, outputPath); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"filePath": outputPath})
|
|
}
|
|
|
|
func (h *ExportHandler) ExportFolderZip(c *gin.Context) {
|
|
userID := c.GetInt64("userID")
|
|
|
|
folderID, err := strconv.ParseInt(c.Param("folderId"), 10, 64)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid folder id"})
|
|
return
|
|
}
|
|
|
|
folderTree, err := h.db.GetFolderTree(userID, folderID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
noteInfoTree := convertNoteToNoteInfo(folderTree)
|
|
|
|
outputPath, err := h.getTempExportPath(folderTree.Title, ".zip")
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
if err := h.exportSvc.ExportFolderZip(folderTree.Title, noteInfoTree.Children, outputPath); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"filePath": outputPath})
|
|
}
|
|
|
|
func (h *ExportHandler) ExportAllZip(c *gin.Context) {
|
|
userID := c.GetInt64("userID")
|
|
|
|
allNotesTree, err := h.db.GetAllNotesTree(userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
noteInfos := make([]*services.NoteInfo, len(allNotesTree))
|
|
for i, noteTree := range allNotesTree {
|
|
noteInfos[i] = convertNoteTreeToNoteInfo(noteTree)
|
|
}
|
|
|
|
outputPath, err := h.getTempExportPath("所有笔记", ".zip")
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
if err := h.exportSvc.ExportAllZip(noteInfos, outputPath); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"filePath": outputPath})
|
|
}
|
|
|
|
func (h *ExportHandler) getTempExportPath(title, ext string) (string, error) {
|
|
tmpDir := filepath.Join(os.TempDir(), "kenaito-notebook-export")
|
|
if err := os.MkdirAll(tmpDir, 0755); err != nil {
|
|
return "", fmt.Errorf("failed to create temp export dir: %w", err)
|
|
}
|
|
|
|
safeName := h.exportSvc.GetSafeFilename(title)
|
|
return filepath.Join(tmpDir, fmt.Sprintf("%s%s", safeName, ext)), nil
|
|
}
|
|
|
|
func convertNoteToNoteInfo(note *models.Note) *services.NoteInfo {
|
|
if note == nil {
|
|
return nil
|
|
}
|
|
|
|
info := &services.NoteInfo{
|
|
Title: note.Title,
|
|
Content: note.Content,
|
|
IsFolder: note.IsFolder,
|
|
}
|
|
|
|
if note.Children != nil && len(note.Children) > 0 {
|
|
info.Children = make([]*services.NoteInfo, len(note.Children))
|
|
for i, child := range note.Children {
|
|
info.Children[i] = convertNoteToNoteInfo(child)
|
|
}
|
|
}
|
|
|
|
return info
|
|
}
|
|
|
|
func convertNoteTreeToNoteInfo(noteTree *models.NoteTree) *services.NoteInfo {
|
|
if noteTree == nil {
|
|
return nil
|
|
}
|
|
|
|
info := &services.NoteInfo{
|
|
Title: noteTree.Title,
|
|
Content: noteTree.Content,
|
|
IsFolder: noteTree.IsFolder,
|
|
}
|
|
|
|
if noteTree.Children != nil && len(noteTree.Children) > 0 {
|
|
info.Children = make([]*services.NoteInfo, len(noteTree.Children))
|
|
for i, child := range noteTree.Children {
|
|
info.Children[i] = convertNoteTreeToNoteInfo(child)
|
|
}
|
|
}
|
|
|
|
return info
|
|
}
|