feat: 初始化 kenaito-notebook 桌面记事本项目
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user