Files

268 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DocSystem(MxsDoc)HTTP 接口文档
目标系统:MxsDoc / DocSystem V2.02.71
地址:`http://172.1.4.31:8100/DocSystem`
前端入口:`/DocSystem/web/index.html` → `projects.html` → `project.html?vid=<仓库ID>`
本文档由前端 JS 逆向 + 逐接口实测得出,用于支撑 `scripts/docsys.py`。
---
## 通用约定
- 凭证配置(`scripts/docsys.py` 读取顺序:命令行参数 > `~/.docsys/config.json` > 环境变量 > 内置默认地址):
```json
// ~/.docsys/config.json
{"baseUrl": "http://172.1.4.31:8100/DocSystem", "user": "x@y.com", "password": "xxx"}
```
环境变量:`DOCSYS_BASE_URL` / `DOCSYS_USER` / `DOCSYS_PASSWORD`。
仓库默认库可用 `DOCSYS_DEFAULT_REPO` 覆盖。**凭证不要提交进代码库。**
- 全部接口为 `POST`,表单编码 `application/x-www-form-urlencoded; charset=UTF-8`
(仅 `uploadDoc.do` 为 `multipart/form-data`)。
- 必须带请求头 `X-Requested-With: XMLHttpRequest`。
- 会话靠 Cookie 维持:`JSESSIONID`、`dstoken`(= base64(密码))、`dsuser`(= 用户名)。
`rememberMe=1` 时服务端下发 `dstoken`/`dsuser` 用于自动登录。
- 响应统一 JSON:`{"status":"ok"|"fail","data":...,"msgInfo":"...","msgData":...}`。
少数接口(如 `getDocContent.do`)返回纯文本。
- 节点类型:`type=1` 文件,`type=2` 目录。
- 时间字段为毫秒时间戳。
## 鉴权
### POST `User/login.do`
| 参数 | 说明 |
|---|---|
| `userName` | 邮箱或手机号 |
| `pwd` | 密码经 base64 编码后的字符串(标准 base64,非 URL-safe) |
| `rememberMe` | `1` 记住登录,`0` 不记住 |
成功返回 `data` 为用户对象(`id`/`name`/`realName`/`role`/…)。
### POST `User/logout.do`
无参数。
### POST `User/getLoginUser.do`
无参数,返回当前登录用户。可用于探测会话是否有效。
---
## 仓库
### POST `Repos/getReposList.do`
无参数。返回 `data` 为仓库数组:
`{id, name, info, type, verCtrl, path, owner, ...}`
实测可见仓库:
| id | 名称 | 说明 |
|---|---|---|
| 1 | 意见与反馈 | 当前账号可新增/编辑,不可删除/下载 |
| **2** | **研发管理配置库** | **CLI 默认仓库**(`DEFAULT_REPO_NAME`),基本只读,部分目录可下载 |
| 5 | 常用工具 | 只读 |
| 6 | 临时仓库 | 无访问权限 |
> **约定**:`scripts/docsys.py` 中若省略仓库参数,默认操作 id=2「研发管理配置库」。
> 判定规则:第一个位置参数以 `/` 或 `./` 开头则视为路径(仓库取默认),否则视为仓库 id/名称。
### POST `Repos/getDocSysConfig.do`
无参数,返回系统配置(如 `defaultReposStorePath`)。
---
## 目录列举
### POST `Repos/getSubDocList.do`
| 参数 | 说明 |
|---|---|
| `vid` | 仓库 id |
| `docId` | 目录 docId(**实测服务端不使用**,仅随请求透传) |
| `path` | 目录路径,仓库根为 `""`,其余以 `/` 结尾 |
| `name` | 目录名。服务端取 `path + name` 作为目标目录 |
| `sort` | 排序方式,`0` 名称 |
| `needLockState` | `1` |
| `shareId` | 可传空 |
**关键结论**:目标目录 = `path + name`。传 `path="a/"`、`name=""` 与 `path=""`、`name="a"`
等价;但传 `path="a/"` 且 `name="a"` 会变成 `a/a` 从而返回空。
返回 `data` 为节点数组,节点字段:
`docId, pid, path, name, type, level, size, checkSum, createTime, latestEditTime,
latestEditorName, creatorName, localRootPath, reposPath, ...`
其中 `path` 是**节点所在目录**的路径,节点完整路径 = `path + name`。
---
## 权限
### POST `Repos/getUserDocAuth.do`
| 参数 | 说明 |
|---|---|
| `docId` | 目录 docId,仓库根为 `0` |
| `reposId` | 仓库 id |
| `path` | 目录自身路径 |
| `name` | 目录名 |
返回 `data`:`{access, addEn, editEn, deleteEn, downloadEn, isAdmin, uploadSize, ...}`
实测(账号 `qian.huang@sunyard.com`,仓库 1):
```
access=1 addEn=1 editEn=1 deleteEn=0 downloadEn=0 isAdmin=0
```
注意:**rename / move 在服务端按"删除 + 新增"鉴权**,因此即使 `addEn=1`,
`deleteEn=0` 时重命名和移动同样会被拒绝,报错为「您没有该目录的删除权限」。
### 权限是逐目录授予的,不是仓库级
同一个仓库里不同目录的权限可以完全不同。实测:
| 仓库 / 目录 | access | addEn | editEn | deleteEn | downloadEn |
|---|---|---|---|---|---|
| 2 研发管理配置库 `/`(根) | 1 | 0 | 0 | 0 | 0 |
| 2 `/Sunyard/Docs/开发流程` | 1 | 0 | 0 | 0 | **1** |
| 2 `/Sunyard/Dev/产品/系统研发/工具` | 1 | **1** | **1** | **1** | **1** |
| 1 意见与反馈 `/`(根) | 1 | 1 | 1 | 0 | 0 |
所以**不能凭仓库名推断权限**,写操作前务必先查 `getUserDocAuth`。
---
## 写操作
### POST `Doc/addDoc.do`(新建文件 / 目录)
| 参数 | 说明 |
|---|---|
| `reposId` | 仓库 id |
| `type` | `1` 文件,`2` 目录 |
| `pid` | 父目录 docId,仓库根为 `0` |
| `path` | **父目录完整路径 + `/`**,仓库根为 `""` |
| `name` | 新节点名 |
| `content` | 文本文件内容;建目录传空 |
返回 `data` 为新节点,`msgData` 为 `isNewNode`。
> ⚠️ **实测:`content` 被服务端忽略。** 即使传了内容,建出来也是 0 字节空文件
> (响应 `size=0`,随后 `getDocContent` 读不到任何内容)。
> 要创建带内容的文件必须改用 `Doc/uploadDoc.do`(CLI 的 `touch` 已自动走这条路)。
### POST `Doc/renameDoc.do`
| 参数 | 说明 |
|---|---|
| `reposId` | 仓库 id |
| `docId` | 节点 docId |
| `pid` | 父目录 docId |
| `type` | 节点类型 |
| `level` | 节点层级 |
| `path` | 节点**自身所在目录**路径 |
| `name` | 原名 |
| `dstName` | 新名 |
### POST `Doc/deleteDoc.do`
| 参数 | 说明 |
|---|---|
| `reposId` | 仓库 id |
| `docId` | 节点 docId |
| `pid` | 父目录 docId |
| `path` | 节点自身所在目录路径 |
| `name` | 节点名 |
删除目录时为递归删除。
### POST `Doc/moveDoc.do`
| 参数 | 说明 |
|---|---|
| `reposId` | 仓库 id |
| `docId` | 节点 docId |
| `type` | 节点类型 |
| `srcLevel` | 源层级 |
| `dstLevel` | 目标层级(父目录 level + 1;移到仓库根为 `0`) |
| `srcPid` | 源父目录 docId |
| `dstPid` | 目标父目录 docId,仓库根为 `0` |
| `srcPath` | 源目录路径 |
| `srcName` | 源名 |
| `dstPath` | **目标父目录完整路径 + `/`**,仓库根为 `""` |
| `dstName` | 目标名(可与源名不同,即改名 + 移动) |
### POST `Doc/copyDoc.do`
参数同 `moveDoc`。
---
## 上传 / 下载
### POST `Doc/uploadDoc.do`(multipart/form-data)
| 字段 | 说明 |
|---|---|
| `reposId` | 仓库 id |
| `path` | **目标目录完整路径 + `/`** |
| `name` | 远端文件名 |
| `size` | 文件字节数 |
| `checkSum` | 文件 MD5 |
| `uploadFile` | 文件内容(文件域) |
| `commitMsg` | 提交说明,可空 |
| `dirPath` | 文件夹上传标记,可空 |
大文件走分片:`chunkNum` / `cutSize` / `chunkIndex` / `chunkSize` / `chunkHash` /
`combineDisabled=1`,分片全部传完再调 `Doc/combineChunks.do`。
### POST `Doc/downloadDocPrepare.do`
| 参数 | 说明 |
|---|---|
| `reposId`, `docId`, `pid`, `path`, `name` | 目标节点 |
| `downloadType` | `1` 单文件 |
| `downloadList` | 可空 |
返回 `data`:`{path, name, targetPath, targetName}`,`msgData` 为 `deleteFlag`。
若 `msgData == 5` 表示目录正在打包,用 `data.id` 轮询
`Doc/queryDownloadPrepareTask.do`(参数 `taskId`),每 2 秒一次,直到 `msgData == 6`。
### GET `Doc/downloadDoc.do?...`
查询串:`vid, path, name, targetPath, targetName, deleteFlag, encryptEn=1`(值需 URL 编码)。
> 实测:直接调 `Doc/getDocFileLink.do` 拿到的链接指向 `tmp/History/rdata/<commitId>/...`
> 历史目录,该文件通常不存在,会返回 500。**必须走 `downloadDocPrepare` 流程。**
---
## 读取 / 搜索
### POST `Doc/searchDoc.do`
| 参数 | 说明 |
|---|---|
| `searchWord` | 关键词 |
| `sort` | `0` |
| `reposId` | 仓库 id |
| `path` | 限定目录范围,全库传 `""` |
返回 `data` 为命中项,`hitType`:`1` 文件名命中,`3` 正文命中;
`content` 为正文的 base64 编码;`dataEx` 为命中总数。
### POST `Doc/getDocContent.do`
| 参数 | 说明 |
|---|---|
| `reposId`, `docId`, `pid`, `path`, `name` | 目标文件 |
返回**纯文本**,响应以 `ok` 开头,后面才是文件正文,解析时须去掉前两个字符。
### POST `Doc/getDoc.do`
| 参数 | 说明 |
|---|---|
| `reposId`, `docId`, `pid`, `path`, `name` | 目标节点 |
| `docType` | `0` 不读取正文和备注 |
返回节点元信息。
---
## 已探明但未使用的接口
- `Doc/lockDoc.do` / `Doc/unlockDoc.do` — 文件锁定
- `Doc/executeDoc.do`、`Doc/refreshDoc.do`
- `Doc/checkChunkUploaded.do`、`Doc/combineChunks.do`、`Doc/getMaxThreadCount.do` — 分片上传
- `Doc/getDocFileLink.do`、`Doc/getZipDocFileLink.do` — 预览/下载链接(下载场景不可靠,见上)
- `Bussiness/getDocOfficeLink.do`、`Bussiness/getDocCadLink.do` — 在线预览
- `Bussiness/addDocShare.do`、`Doc/getDocShare.do` — 分享
- `Doc/querySystemLog.do` — 操作日志
- `Repos/getReposInitMenu.do` — 目录树初始化菜单