🎨 Support exporting .sy.zip after selecting multiple documents https://github.com/siyuan-note/siyuan/issues/14484

Signed-off-by: Daniel <845765@qq.com>
This commit is contained in:
Daniel 2026-01-16 13:52:32 +08:00
parent 315618a77c
commit 65532aec99
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
4 changed files with 51 additions and 20 deletions

View file

@ -4,7 +4,7 @@ import {FileFilter, ipcRenderer} from "electron";
import * as path from "path";
/// #endif
import {MenuItem} from "./Menu";
import {getDisplayName, getNotebookName, getTopPaths, useShell, pathPosix} from "../util/pathName";
import {getDisplayName, getNotebookName, getTopPaths, pathPosix, useShell} from "../util/pathName";
import {hideMessage, showMessage} from "../dialog/message";
import {fetchPost, fetchSyncPost} from "../util/fetch";
import {onGetnotebookconf} from "./onGetnotebookconf";
@ -158,6 +158,19 @@ const initMultiMenu = (selectItemElements: NodeListOf<Element>, app: App) => {
type: "submenu",
icon: "iconUpload",
submenu: [{
id: "exportSiYuanZip",
label: "SiYuan .sy.zip",
icon: "iconSiYuan",
click: () => {
const msgId = showMessage(window.siyuan.languages.exporting, -1);
fetchPost("/api/export/exportSYs", {
ids: blockIDs,
}, response => {
hideMessage(msgId);
openByMobile(response.data.zip);
});
}
}, {
id: "exportMarkdown",
label: "Markdown .zip",
icon: "iconMarkdown",

View file

@ -406,6 +406,27 @@ func exportNotebookSY(c *gin.Context) {
}
}
func exportSYs(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
idsArg := arg["ids"].([]interface{})
var ids []string
for _, id := range idsArg {
ids = append(ids, id.(string))
}
zipPath := model.ExportSYs(ids)
ret.Data = map[string]interface{}{
"zip": zipPath,
}
}
func exportSY(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
@ -416,10 +437,9 @@ func exportSY(c *gin.Context) {
}
id := arg["id"].(string)
name, zipPath := model.ExportSY(id)
zipPath := model.ExportSYs([]string{id})
ret.Data = map[string]interface{}{
"name": name,
"zip": zipPath,
"zip": zipPath,
}
}

View file

@ -315,6 +315,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/export/exportNotebookMd", model.CheckAuth, model.CheckAdminRole, exportNotebookMd)
ginServer.Handle("POST", "/api/export/exportMds", model.CheckAuth, model.CheckAdminRole, exportMds)
ginServer.Handle("POST", "/api/export/exportMd", model.CheckAuth, model.CheckAdminRole, exportMd)
ginServer.Handle("POST", "/api/export/exportSYs", model.CheckAuth, model.CheckAdminRole, exportSYs)
ginServer.Handle("POST", "/api/export/exportSY", model.CheckAuth, model.CheckAdminRole, exportSY)
ginServer.Handle("POST", "/api/export/exportNotebookSY", model.CheckAuth, model.CheckAdminRole, exportNotebookSY)
ginServer.Handle("POST", "/api/export/exportMdContent", model.CheckAuth, model.CheckAdminRole, exportMdContent)

View file

@ -451,27 +451,24 @@ func ExportNotebookSY(id string) (zipPath string) {
return
}
func ExportSY(id string) (name, zipPath string) {
block := treenode.GetBlockTree(id)
if nil == block {
logging.LogErrorf("not found block [%s]", id)
return
}
boxID := block.BoxID
box := Conf.Box(boxID)
func ExportSYs(ids []string) (zipPath string) {
block := treenode.GetBlockTree(ids[0])
box := Conf.Box(block.BoxID)
baseFolderName := path.Base(block.HPath)
if "." == baseFolderName {
baseFolderName = path.Base(block.Path)
}
rootPath := block.Path
docPaths := []string{rootPath}
docFiles := box.ListFiles(strings.TrimSuffix(block.Path, ".sy"))
for _, docFile := range docFiles {
docPaths = append(docPaths, docFile.path)
var docPaths []string
bts := treenode.GetBlockTrees(ids)
for _, bt := range bts {
docPaths = append(docPaths, bt.Path)
docFiles := box.ListFiles(strings.TrimSuffix(bt.Path, ".sy"))
for _, docFile := range docFiles {
docPaths = append(docPaths, docFile.path)
}
}
zipPath = exportSYZip(boxID, path.Dir(rootPath), baseFolderName, docPaths)
name = util.GetTreeID(block.Path)
zipPath = exportSYZip(block.BoxID, path.Dir(block.Path), baseFolderName, docPaths)
return
}