🧑‍💻 Add a kernel API /api/filetree/moveDocsByID https://github.com/siyuan-note/siyuan/issues/13247

This commit is contained in:
Daniel 2024-12-05 10:49:54 +08:00
parent c1fd34f57b
commit f21f0ea60b
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
4 changed files with 145 additions and 32 deletions

75
API.md
View file

@ -73,7 +73,8 @@
* Endpoint: `http://127.0.0.1:6806`
* Both are POST methods
* An interface with parameters is required, the parameter is a JSON string, placed in the body, and the header Content-Type is `application/json`
* An interface with parameters is required, the parameter is a JSON string, placed in the body, and the header
Content-Type is `application/json`
* Return value
````json
@ -328,7 +329,8 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
```
* `notebook`: Notebook ID
* `path`: Document path, which needs to start with / and separate levels with / (path here corresponds to the database hpath field)
* `path`: Document path, which needs to start with / and separate levels with / (path here corresponds to the
database hpath field)
* `markdown`: GFM Markdown content
* Return value
@ -381,8 +383,8 @@ Rename a document by `id`:
}
```
* `id`: Document ID
* `title`: New document title
* `id`: Document ID
* `title`: New document title
* Return value
```json
@ -416,7 +418,7 @@ Rename a document by `id`:
"data": null
}
```
Remove a document by `id`:
* `/api/filetree/removeDocByID`
@ -428,7 +430,7 @@ Remove a document by `id`:
}
```
* `id`: Document ID
* `id`: Document ID
* Return value
```json
@ -465,6 +467,30 @@ Remove a document by `id`:
}
```
Move documents by `id`:
* `/api/filetree/moveDocsByID`
* Parameters
```json
{
"fromIDs": ["20210917220056-yxtyl7i"],
"toID": "20210817205410-2kvfpfn"
}
```
* `fromIDs`: Source docs' IDs
* `toID`: Target parent ID
* Return value
```json
{
"code": 0,
"msg": "",
"data": null
}
```
### Get human-readable path based on path
* `/api/filetree/getHPathByPath`
@ -510,7 +536,7 @@ Remove a document by `id`:
"data": "/foo/bar"
}
```
### Get storage path based on ID
* `/api/filetree/getPathByID`
@ -522,7 +548,7 @@ Remove a document by `id`:
}
```
* `id`: Block ID
* `id`: Block ID
* Return value
```json
@ -545,8 +571,8 @@ Remove a document by `id`:
}
```
* `path`: Human-readable path
* `notebook`: Notebook ID
* `path`: Human-readable path
* `notebook`: Notebook ID
* Return value
```json
@ -570,7 +596,8 @@ Remove a document by `id`:
* `"/assets/"`: workspace/data/assets/ folder
* `"/assets/sub/"`: workspace/data/assets/sub/ folder
Under normal circumstances, it is recommended to use the first method, which is stored in the assets folder of the workspace, putting in a subdirectory has some side effects, please refer to the assets chapter of the user guide.
Under normal circumstances, it is recommended to use the first method, which is stored in the assets folder of the
workspace, putting in a subdirectory has some side effects, please refer to the assets chapter of the user guide.
* `file[]`: Uploaded file list
* Return value
@ -588,7 +615,9 @@ Remove a document by `id`:
```
* `errFiles`: List of filenames with errors in upload processing
* `succMap`: For successfully processed files, the key is the file name when uploading, and the value is assets/foo-id.png, which is used to replace the asset link address in the existing Markdown content with the uploaded address
* `succMap`: For successfully processed files, the key is the file name when uploading, and the value is
assets/foo-id.png, which is used to replace the asset link address in the existing Markdown content with the
uploaded address
## Blocks
@ -613,7 +642,8 @@ Remove a document by `id`:
* `previousID`: The ID of the previous block, used to anchor the insertion position
* `parentID`: The ID of the parent block, used to anchor the insertion position
`nextID`, `previousID`, and `parentID` must have at least one value, using priority: `nextID` > `previousID` > `parentID`
`nextID`, `previousID`, and `parentID` must have at least one value, using priority: `nextID` > `previousID` >
`parentID`
* Return value
```json
@ -820,7 +850,8 @@ Remove a document by `id`:
* `id`: Block ID to move
* `previousID`: The ID of the previous block, used to anchor the insertion position
* `parentID`: The ID of the parent block, used to anchor the insertion position, `previousID` and `parentID` cannot be empty at the same time, if they exist at the same time, `previousID` will be used first
* `parentID`: The ID of the parent block, used to anchor the insertion position, `previousID` and `parentID` cannot
be empty at the same time, if they exist at the same time, `previousID` will be used first
* Return value
```json
@ -860,7 +891,7 @@ Remove a document by `id`:
}
```
* `id`: Block ID to fold
* `id`: Block ID to fold
* Return value
```json
@ -882,7 +913,7 @@ Remove a document by `id`:
}
```
* `id`: Block ID to unfold
* `id`: Block ID to unfold
* Return value
```json
@ -1380,7 +1411,8 @@ Remove a document by `id`:
"timeout": 7000
}
```
* `timeout`: The duration of the message display in milliseconds. This field can be omitted, the default is 7000 milliseconds
* `timeout`: The duration of the message display in milliseconds. This field can be omitted, the default is 7000
milliseconds
* Return value
```json
@ -1405,7 +1437,8 @@ Remove a document by `id`:
"timeout": 7000
}
```
* `timeout`: The duration of the message display in milliseconds. This field can be omitted, the default is 7000 milliseconds
* `timeout`: The duration of the message display in milliseconds. This field can be omitted, the default is 7000
milliseconds
* Return value
```json
@ -1457,7 +1490,8 @@ Remove a document by `id`:
* `base32` | `base32-std`
* `base32-hex`
* `hex`
* `responseEncoding`: The encoding scheme used by `body` in response data, default is `text`, optional values are as follows
* `responseEncoding`: The encoding scheme used by `body` in response data, default is `text`, optional values are as
follows
* `text`
* `base64` | `base64-std`
@ -1484,7 +1518,8 @@ Remove a document by `id`:
}
```
* `bodyEncoding`: The encoding scheme used by `body`, is consistent with field `responseEncoding` in request, default is `text`, optional values are as follows
* `bodyEncoding`: The encoding scheme used by `body`, is consistent with field `responseEncoding` in request,
default is `text`, optional values are as follows
* `text`
* `base64` | `base64-std`

View file

@ -381,8 +381,8 @@
}
```
* `id`:文档 ID
* `title`:新标题
* `id`:文档 ID
* `title`:新标题
* 返回值
```json
@ -416,7 +416,7 @@
"data": null
}
```
通过 `id` 删除文档:
* `/api/filetree/removeDocByID`
@ -428,7 +428,7 @@
}
```
* `id`:文档 ID
* `id`:文档 ID
* 返回值
```json
@ -465,6 +465,30 @@
}
```
通过 `id` 移动文档:
* `/api/filetree/moveDocsByID`
* 参数
```json
{
"fromIDs": ["20210917220056-yxtyl7i"],
"toID": "20210817205410-2kvfpfn"
}
```
* `fromIDs`:源文档 ID
* `toID`:目标父文档 ID
* 返回值
```json
{
"code": 0,
"msg": "",
"data": null
}
```
### 根据路径获取人类可读路径
* `/api/filetree/getHPathByPath`
@ -522,7 +546,7 @@
}
```
* `id`:块 ID
* `id`:块 ID
* 返回值
```json
@ -545,8 +569,8 @@
}
```
* `path`:人类可读路径
* `notebook`:笔记本 ID
* `path`:人类可读路径
* `notebook`:笔记本 ID
* 返回值
```json
@ -860,7 +884,7 @@
}
```
* `id`:待折叠块的 ID
* `id`:待折叠块的 ID
* 返回值
```json
@ -882,7 +906,7 @@
}
```
* `id`:待展开块的 ID
* `id`:待展开块的 ID
* 返回值
```json
@ -1063,7 +1087,7 @@
]
}
```
### 提交事务
* `/api/sqlite/flushTransaction`

View file

@ -472,9 +472,7 @@ func moveDocs(c *gin.Context) {
if util.InvalidIDPattern(toNotebook, ret) {
return
}
callback := arg["callback"]
err := model.MoveDocs(fromPaths, toNotebook, toPath, callback)
if err != nil {
ret.Code = -1
@ -484,6 +482,61 @@ func moveDocs(c *gin.Context) {
}
}
func moveDocsByID(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
fromIDsArg := arg["fromIDs"].([]any)
var fromIDs []string
for _, fromIDArg := range fromIDsArg {
fromID := fromIDArg.(string)
if util.InvalidIDPattern(fromID, ret) {
return
}
fromIDs = append(fromIDs, fromID)
}
toID := arg["toID"].(string)
if util.InvalidIDPattern(toID, ret) {
return
}
var fromPaths []string
for _, fromID := range fromIDs {
tree, err := model.LoadTreeByBlockID(fromID)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = map[string]interface{}{"closeTimeout": 7000}
return
}
fromPaths = append(fromPaths, tree.Path)
}
fromPaths = gulu.Str.RemoveDuplicatedElem(fromPaths)
toTree, err := model.LoadTreeByBlockID(toID)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = map[string]interface{}{"closeTimeout": 7000}
return
}
toNotebook := toTree.Box
toPath := toTree.Path
callback := arg["callback"]
err = model.MoveDocs(fromPaths, toNotebook, toPath, callback)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
ret.Data = map[string]interface{}{"closeTimeout": 7000}
return
}
}
func removeDoc(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)

View file

@ -109,6 +109,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/filetree/removeDocByID", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, removeDocByID)
ginServer.Handle("POST", "/api/filetree/removeDocs", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, removeDocs)
ginServer.Handle("POST", "/api/filetree/moveDocs", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, moveDocs)
ginServer.Handle("POST", "/api/filetree/moveDocsByID", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, moveDocsByID)
ginServer.Handle("POST", "/api/filetree/duplicateDoc", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, duplicateDoc)
ginServer.Handle("POST", "/api/filetree/getHPathByPath", model.CheckAuth, getHPathByPath)
ginServer.Handle("POST", "/api/filetree/getHPathsByPaths", model.CheckAuth, getHPathsByPaths)