瀏覽代碼

Merge remote-tracking branch 'origin/dev' into dev

Vanessa 1 年之前
父節點
當前提交
f2903bb3fd
共有 4 個文件被更改,包括 63 次插入8 次删除
  1. 2 1
      app/src/protyle/wysiwyg/index.ts
  2. 23 0
      kernel/api/export.go
  3. 1 0
      kernel/api/router.go
  4. 37 7
      kernel/model/export.go

+ 2 - 1
app/src/protyle/wysiwyg/index.ts

@@ -1882,7 +1882,8 @@ export class WYSIWYG {
                     }
                 } else if (linkAddress) {
                     /// #if !BROWSER
-                    if (0 > linkAddress.indexOf("://")) {
+                    if (0 > linkAddress.indexOf(":")) {
+                        // 使用 : 判断,不使用 :// 判断 Open external application protocol invalid https://github.com/siyuan-note/siyuan/issues/10075
                         // Support click to open hyperlinks like `www.foo.com` https://github.com/siyuan-note/siyuan/issues/9986
                         linkAddress = `https://${linkAddress}`;
                     }

+ 23 - 0
kernel/api/export.go

@@ -33,6 +33,29 @@ import (
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 
+func exportAttributeView(c *gin.Context) {
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	arg, ok := util.JsonArg(c, ret)
+	if !ok {
+		return
+	}
+
+	avID := arg["id"].(string)
+	zipPath, err := model.ExportAv2CSV(avID)
+	if nil != err {
+		ret.Code = 1
+		ret.Msg = err.Error()
+		ret.Data = map[string]interface{}{"closeTimeout": 7000}
+		return
+	}
+
+	ret.Data = map[string]interface{}{
+		"zip": zipPath,
+	}
+}
+
 func exportEPUB(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)

+ 1 - 0
kernel/api/router.go

@@ -283,6 +283,7 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/export/exportODT", model.CheckAuth, exportODT)
 	ginServer.Handle("POST", "/api/export/exportRTF", model.CheckAuth, exportRTF)
 	ginServer.Handle("POST", "/api/export/exportEPUB", model.CheckAuth, exportEPUB)
+	ginServer.Handle("POST", "/api/export/exportAttributeView", model.CheckAuth, exportAttributeView)
 
 	ginServer.Handle("POST", "/api/import/importStdMd", model.CheckAuth, model.CheckReadonly, importStdMd)
 	ginServer.Handle("POST", "/api/import/importData", model.CheckAuth, model.CheckReadonly, importData)

+ 37 - 7
kernel/model/export.go

@@ -56,8 +56,8 @@ import (
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 
-func ExportAv2CSV(avID string) (csvPath string, err error) {
-	// TODO: Database table view supports export as CSV https://github.com/siyuan-note/siyuan/issues/10072
+func ExportAv2CSV(avID string) (zipPath string, err error) {
+	// Database block supports export as CSV https://github.com/siyuan-note/siyuan/issues/10072
 
 	attrView, err := av.ParseAttributeView(avID)
 	if nil != err {
@@ -69,25 +69,26 @@ func ExportAv2CSV(avID string) (csvPath string, err error) {
 		return
 	}
 
+	name := util.FilterFileName(attrView.Name)
+
 	table, err := renderAttributeViewTable(attrView, view)
 	if nil != err {
 		logging.LogErrorf("render attribute view [%s] table failed: %s", avID, err)
 		return
 	}
 
-	tmpExport := filepath.Join(util.TempDir, "export", "csv")
-	if err = os.MkdirAll(tmpExport, 0755); nil != err {
-		logging.LogErrorf("mkdir [%s] failed: %s", tmpExport, err)
+	exportFolder := filepath.Join(util.TempDir, "export", "csv", name)
+	if err = os.MkdirAll(exportFolder, 0755); nil != err {
+		logging.LogErrorf("mkdir [%s] failed: %s", exportFolder, err)
 		return
 	}
-	csvPath = filepath.Join(tmpExport, avID+".csv")
+	csvPath := filepath.Join(exportFolder, name+".csv")
 
 	f, err := os.OpenFile(csvPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
 	if nil != err {
 		logging.LogErrorf("open [%s] failed: %s", csvPath, err)
 		return
 	}
-	defer f.Close()
 
 	writer := csv.NewWriter(f)
 
@@ -97,6 +98,7 @@ func ExportAv2CSV(avID string) (csvPath string, err error) {
 	}
 	if err = writer.Write(header); nil != err {
 		logging.LogErrorf("write csv header [%s] failed: %s", header, err)
+		f.Close()
 		return
 	}
 
@@ -136,10 +138,38 @@ func ExportAv2CSV(avID string) (csvPath string, err error) {
 		}
 		if err = writer.Write(rowVal); nil != err {
 			logging.LogErrorf("write csv row [%s] failed: %s", rowVal, err)
+			f.Close()
 			return
 		}
 	}
 	writer.Flush()
+
+	zipPath = exportFolder + ".db.zip"
+	zip, err := gulu.Zip.Create(zipPath)
+	if nil != err {
+		logging.LogErrorf("create export .db.zip [%s] failed: %s", exportFolder, err)
+		f.Close()
+		return
+	}
+
+	if err = zip.AddDirectory("", exportFolder); nil != err {
+		logging.LogErrorf("create export .db.zip [%s] failed: %s", exportFolder, err)
+		f.Close()
+		return
+	}
+
+	if err = zip.Close(); nil != err {
+		logging.LogErrorf("close export .db.zip failed: %s", err)
+		f.Close()
+		return
+	}
+
+	f.Close()
+	removeErr := os.RemoveAll(exportFolder)
+	if nil != removeErr {
+		logging.LogErrorf("remove export folder [%s] failed: %s", exportFolder, removeErr)
+	}
+	zipPath = "/export/" + url.PathEscape(filepath.Base(zipPath))
 	return
 }