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> 环境变量 > 内置默认地址):环境变量:// ~/.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.doDoc/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— 目录树初始化菜单