mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-18 15:40:12 +01:00
🎨 Update av export
This commit is contained in:
parent
3cd6e0d953
commit
376384d4e3
5 changed files with 58 additions and 32 deletions
|
|
@ -35,8 +35,7 @@ func renderAttributeView(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
id := arg["id"].(string)
|
id := arg["id"].(string)
|
||||||
nodeID := arg["nodeID"].(string)
|
view, attrView, err := model.RenderAttributeView(id)
|
||||||
view, attrView, err := model.RenderAttributeView(id, nodeID)
|
|
||||||
if nil != err {
|
if nil != err {
|
||||||
ret.Code = -1
|
ret.Code = -1
|
||||||
ret.Msg = err.Error()
|
ret.Msg = err.Error()
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ import (
|
||||||
type AttributeView struct {
|
type AttributeView struct {
|
||||||
Spec int `json:"spec"` // 格式版本
|
Spec int `json:"spec"` // 格式版本
|
||||||
ID string `json:"id"` // 属性视图 ID
|
ID string `json:"id"` // 属性视图 ID
|
||||||
NodeID string `json:"nodeID"` // 属性视图所在节点 ID
|
|
||||||
Name string `json:"name"` // 属性视图名称
|
Name string `json:"name"` // 属性视图名称
|
||||||
KeyValues []*KeyValues `json:"keyValues"` // 属性视图属性列值
|
KeyValues []*KeyValues `json:"keyValues"` // 属性视图属性列值
|
||||||
ViewID string `json:"viewID"` // 当前视图 ID
|
ViewID string `json:"viewID"` // 当前视图 ID
|
||||||
|
|
@ -386,7 +385,7 @@ type Viewable interface {
|
||||||
GetID() string
|
GetID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAttributeView(id, nodeID string) (ret *AttributeView) {
|
func NewAttributeView(id string) (ret *AttributeView) {
|
||||||
view := NewView()
|
view := NewView()
|
||||||
key := NewKey(ast.NewNodeID(), "Block", KeyTypeBlock)
|
key := NewKey(ast.NewNodeID(), "Block", KeyTypeBlock)
|
||||||
ret = &AttributeView{
|
ret = &AttributeView{
|
||||||
|
|
@ -395,7 +394,6 @@ func NewAttributeView(id, nodeID string) (ret *AttributeView) {
|
||||||
KeyValues: []*KeyValues{{Key: key}},
|
KeyValues: []*KeyValues{{Key: key}},
|
||||||
ViewID: view.ID,
|
ViewID: view.ID,
|
||||||
Views: []*View{view},
|
Views: []*View{view},
|
||||||
NodeID: nodeID,
|
|
||||||
}
|
}
|
||||||
view.Table.Columns = []*ViewTableColumn{{ID: key.ID}}
|
view.Table.Columns = []*ViewTableColumn{{ID: key.ID}}
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,11 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func RenderAttributeView(avID, nodeID string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
|
func RenderAttributeView(avID string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
|
||||||
waitForSyncingStorages()
|
waitForSyncingStorages()
|
||||||
|
|
||||||
if avJSONPath := av.GetAttributeViewDataPath(avID); !gulu.File.IsExist(avJSONPath) {
|
if avJSONPath := av.GetAttributeViewDataPath(avID); !gulu.File.IsExist(avJSONPath) {
|
||||||
attrView = av.NewAttributeView(avID, nodeID)
|
attrView = av.NewAttributeView(avID)
|
||||||
if err = av.SaveAttributeView(attrView); nil != err {
|
if err = av.SaveAttributeView(attrView); nil != err {
|
||||||
logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
|
logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
|
||||||
return
|
return
|
||||||
|
|
@ -103,14 +103,6 @@ func RenderAttributeView(avID, nodeID string) (viewable av.Viewable, attrView *a
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if "" == attrView.NodeID {
|
|
||||||
attrView.NodeID = nodeID
|
|
||||||
if err = av.SaveAttributeView(attrView); nil != err {
|
|
||||||
logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if 1 > len(attrView.Views) {
|
if 1 > len(attrView.Views) {
|
||||||
err = av.ErrViewNotFound
|
err = av.ErrViewNotFound
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -1380,7 +1380,6 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
|
||||||
}
|
}
|
||||||
return ast.WalkContinue
|
return ast.WalkContinue
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出自定义排序
|
// 导出自定义排序
|
||||||
|
|
|
||||||
|
|
@ -141,24 +141,23 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||||
if !entering {
|
if !entering || "" == n.ID {
|
||||||
return ast.WalkContinue
|
return ast.WalkContinue
|
||||||
}
|
}
|
||||||
if "" != n.ID {
|
|
||||||
newNodeID := ast.NewNodeID()
|
|
||||||
blockIDs[n.ID] = newNodeID
|
|
||||||
oldNodeID := n.ID
|
|
||||||
n.ID = newNodeID
|
|
||||||
n.SetIALAttr("id", newNodeID)
|
|
||||||
|
|
||||||
// 重新指向数据库属性值
|
newNodeID := ast.NewNodeID()
|
||||||
ial := parse.IAL2Map(n.KramdownIAL)
|
blockIDs[n.ID] = newNodeID
|
||||||
for k, v := range ial {
|
oldNodeID := n.ID
|
||||||
if strings.HasPrefix(k, NodeAttrNamePrefixAvKey) {
|
n.ID = newNodeID
|
||||||
v = strings.ReplaceAll(v, oldNodeID, newNodeID)
|
n.SetIALAttr("id", newNodeID)
|
||||||
n.SetIALAttr(k, v)
|
|
||||||
avBlockIDs[oldNodeID] = newNodeID
|
// 重新指向数据库属性值
|
||||||
}
|
ial := parse.IAL2Map(n.KramdownIAL)
|
||||||
|
for k, v := range ial {
|
||||||
|
if strings.HasPrefix(k, NodeAttrNamePrefixAvKey) {
|
||||||
|
v = strings.ReplaceAll(v, oldNodeID, newNodeID)
|
||||||
|
n.SetIALAttr(k, v)
|
||||||
|
avBlockIDs[oldNodeID] = newNodeID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ast.WalkContinue
|
return ast.WalkContinue
|
||||||
|
|
@ -201,13 +200,23 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
|
||||||
// 将关联的数据库文件移动到 data/storage/av/ 下
|
// 将关联的数据库文件移动到 data/storage/av/ 下
|
||||||
storage := filepath.Join(unzipRootPath, "storage")
|
storage := filepath.Join(unzipRootPath, "storage")
|
||||||
storageAvDir := filepath.Join(storage, "av")
|
storageAvDir := filepath.Join(storage, "av")
|
||||||
|
avIDs := map[string]string{}
|
||||||
|
renameAvPaths := map[string]string{}
|
||||||
if gulu.File.IsExist(storageAvDir) {
|
if gulu.File.IsExist(storageAvDir) {
|
||||||
// 将数据库文件中的块 ID 替换为新的块 ID
|
// 重新生成数据库数据
|
||||||
filepath.Walk(storageAvDir, func(path string, info fs.FileInfo, err error) error {
|
filepath.Walk(storageAvDir, func(path string, info fs.FileInfo, err error) error {
|
||||||
if !strings.HasSuffix(path, ".json") || !ast.IsNodeIDPattern(strings.TrimSuffix(info.Name(), ".json")) {
|
if !strings.HasSuffix(path, ".json") || !ast.IsNodeIDPattern(strings.TrimSuffix(info.Name(), ".json")) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重命名数据库
|
||||||
|
newAvID := ast.NewNodeID()
|
||||||
|
oldAvID := strings.TrimSuffix(info.Name(), ".json")
|
||||||
|
newPath := filepath.Join(filepath.Dir(path), newAvID+".json")
|
||||||
|
renameAvPaths[path] = newPath
|
||||||
|
avIDs[oldAvID] = newAvID
|
||||||
|
|
||||||
|
// 将数据库文件中的块 ID 替换为新的块 ID
|
||||||
data, readErr := os.ReadFile(path)
|
data, readErr := os.ReadFile(path)
|
||||||
if nil != readErr {
|
if nil != readErr {
|
||||||
logging.LogErrorf("read av file [%s] failed: %s", path, readErr)
|
logging.LogErrorf("read av file [%s] failed: %s", path, readErr)
|
||||||
|
|
@ -218,6 +227,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
|
||||||
for oldID, newID := range avBlockIDs {
|
for oldID, newID := range avBlockIDs {
|
||||||
newData = bytes.ReplaceAll(newData, []byte(oldID), []byte(newID))
|
newData = bytes.ReplaceAll(newData, []byte(oldID), []byte(newID))
|
||||||
}
|
}
|
||||||
|
newData = bytes.ReplaceAll(newData, []byte(oldAvID), []byte(newAvID))
|
||||||
if !bytes.Equal(data, newData) {
|
if !bytes.Equal(data, newData) {
|
||||||
if writeErr := os.WriteFile(path, newData, 0644); nil != writeErr {
|
if writeErr := os.WriteFile(path, newData, 0644); nil != writeErr {
|
||||||
logging.LogErrorf("write av file [%s] failed: %s", path, writeErr)
|
logging.LogErrorf("write av file [%s] failed: %s", path, writeErr)
|
||||||
|
|
@ -227,10 +237,38 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 重命名数据库文件
|
||||||
|
for oldPath, newPath := range renameAvPaths {
|
||||||
|
if err = os.Rename(oldPath, newPath); nil != err {
|
||||||
|
logging.LogErrorf("rename av file from [%s] to [%s] failed: %s", oldPath, newPath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
targetStorageAvDir := filepath.Join(util.DataDir, "storage", "av")
|
targetStorageAvDir := filepath.Join(util.DataDir, "storage", "av")
|
||||||
if copyErr := filelock.Copy(storageAvDir, targetStorageAvDir); nil != copyErr {
|
if copyErr := filelock.Copy(storageAvDir, targetStorageAvDir); nil != copyErr {
|
||||||
logging.LogErrorf("copy storage av dir from [%s] to [%s] failed: %s", storageAvDir, targetStorageAvDir, copyErr)
|
logging.LogErrorf("copy storage av dir from [%s] to [%s] failed: %s", storageAvDir, targetStorageAvDir, copyErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重新指向数据库属性值
|
||||||
|
for _, tree := range trees {
|
||||||
|
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||||
|
if !entering || "" == n.ID {
|
||||||
|
return ast.WalkContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
ial := parse.IAL2Map(n.KramdownIAL)
|
||||||
|
for k, v := range ial {
|
||||||
|
if strings.HasPrefix(k, NodeAttrNamePrefixAvKey) || strings.HasPrefix(k, NodeAttrNameAvs) {
|
||||||
|
for oldAvID, newAvID := range avIDs {
|
||||||
|
v = strings.ReplaceAll(v, oldAvID, newAvID)
|
||||||
|
n.SetIALAttr(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ast.WalkContinue
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage 文件夹已在上方处理,所以这里删除源 storage 文件夹,避免后面被拷贝到导入目录下 targetDir
|
// storage 文件夹已在上方处理,所以这里删除源 storage 文件夹,避免后面被拷贝到导入目录下 targetDir
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue