DMS_API.md 19 KB

DMS 接口文档

服务http://121.43.55.7:10081/dmsDMS_HOST 可覆盖) 整理时间:2026-09-16

📍 本文引用的 artifacts / tools / RUNBOOK 都不在本仓库。 这些文件属于另一个项目 F:\yysk\AI_zhaoshang\DMS_Data_Migration\ (本文就是从它的 harness/docs/ 复制过来的)。本文里的链接已改为绝对路径指向那边; 若那边目录挪了位置,链接会失效 —— 记得回来改。 权威来源:服务端自带 OpenAPI dms_openapi.jsonGET /dms/v3/api-docs,实时抓取,比 Apifox 新)

可信度标注:本文每个接口都标了来源。

  • 实测 —— 本项目真实调用过,参数与响应已验证
  • 📄 文档 —— 仅见于 SKILL.md / Apifox / OpenAPI,本项目尚未调用过,用前先小样本验证

1. 通用约定

1.1 鉴权

除登录外所有接口都要在 header 带 token:

token: {access_token}

AuthInterceptor 会拦截 /content/**/model/**/column/**/task/**, 内部回调 OAuth 校验:

POST {oauth}/api/user/getUserByToken
  Header: token
  Body: serviceId=2, strUrl={当前请求URI}

OAuth serviceId 固定传 2(DMS 专用)。

token 通过环境变量传递,不要写进任何文件

export DMS_TOKEN='...'

1.2 请求格式

场景 Content-Type
多数接口 application/x-www-form-urlencoded
文件上传 multipart/form-data

⚠️ model / column 的写接口有个陷阱:OpenAPI 声明它们是 query 参数, 但把大 payload(如 41 字段的 fieldList)放 query string 会触发 HTTP 400一律用 form body。详见 §5.3。

1.3 响应格式

{ "code": 200, "content": ..., "message": "成功" }
code 含义
200 成功
201 无权限
202 数据不存在(栏目为空)
205 无数据 / 模型不存在
212 无效 token
-1 参数错误
214 数据错误

-1/214/205具体触发条件见 §5.4 —— 这几个是实测踩出来的,文档里没有。


2. 接口总览

GET /dms/v3/api-docs 共 82 个端点。按业务分组:

分组 主要端点
栏目 /column/getColumnList/column/getColumnById/column/addColumn/column/update/column/delColumn/column/selectChild
模型 /model/addModel/model/getModelById/model/getModelByName/model/getModelListByPage/model/updateFieldList/model/createModelByOldModel
内容 /content/addContent/content/updateContent/content/selectContentList/content/selectContentById/content/delContentById/content/importJSON
字段库 /param/selectAll/param/addParam
单/多选框 /select/addSelects/select/getSelectByType
类别 /category/addCategorys/category/selectByType
任务 /task/addDataSync/task/run/task/taskLog
权限 /permission/getColumnByPermission
文件 /file/uploadFile

3. 本项目已实测的接口 ✅

这 8 个是本次建栏目真实调用并验证过的。

3.1 GET /dms/v3/api-docs

服务端自带的 OpenAPI 规范。排查接口问题的第一站,比 Apifox 权威。

curl -s "http://${DMS_HOST}/dms/v3/api-docs" -H "token: ${DMS_TOKEN}" -o dms_openapi.json

返回 118KB JSON,含 82 个端点的参数定义。已存档 dms_openapi.json

3.2 POST /column/getColumnList

获取分级栏目树(无参数)。

curl -s -X POST "http://${DMS_HOST}/dms/column/getColumnList" -H "token: ${DMS_TOKEN}"

返回 content顶级栏目数组,每个节点:

字段 说明
id 栏目 id
title 栏目名
type 0 分级栏目 / 1 内容栏目
tag 权限标签,同步 OAuth permissionName
parentId 父栏目 id
level / state 层级 / 状态
columnList 子栏目数组(递归)

实测返回 28 个顶级栏目。树是嵌套的,找子栏目要递归 columnList, 不要只看顶层。

3.3 POST /model/getModelById

curl -s "http://${DMS_HOST}/dms/model/getModelById?modelId=1839" -H "token: ${DMS_TOKEN}"

⚠️ 参数走 query string(不是 form body),modelId 必须带。

content 字段:

字段 说明
modelName 模型名,物理表为 column_{modelName}
modelAlias 中文别名
type 1 基础模型 / 2 栏目模型
fieldList JSON 字符串,见 §5.1
searchField / sortField 实测为 "[]"
pageSize 实测为 20
authorId / authorName 创建者

3.4 POST /model/getModelByName

curl -s "http://${DMS_HOST}/dms/model/getModelByName?modelName=yszs_page_view_model" -H "token: ${DMS_TOKEN}"

参数走 query string。用于幂等检查:建模型前先查名字是否存在。

3.5 POST /model/getModelListByPage

curl -s "http://${DMS_HOST}/dms/model/getModelListByPage?type=2" -H "token: ${DMS_TOKEN}"

唯一参数是 typetype=1 基础模型,type=2 栏目模型。

⚠️ 不传 type 会返回 code=205 无数据(不是空列表)。 同名的 /model/getModelList 无论怎么传都返回 205 —— 用 getModelListByPage

3.6 POST /param/selectAll

查询所有初始字段(无参数)。返回 28 个基础字段模板:

id name type alias
1 summary text 摘要
2 content text 正文内容
3 date_time timestamp 时间
4 text text 文本内容
5 int_num integer 整数类型
6 float_num double 浮点数类型
7 boolean boolean 布尔类型
8 check check 单选框
9 multiple_check mcheck 多选框
11 select type 类别
12 multiple_select mtype 多级类别
20 files file 文件
21 picture varchar 图片

这个表的 name 就是 fieldListfrontType 该填的值。 见 §5.2。

3.7 PUT /model/addModel

创建基础模型

参数(form body):

参数 说明
modelName 字符串 模型名,必须唯一
modelAlias 字符串 中文别名
fieldList JSON 字符串 见 §5.1
searchField "[]" 字面量空数组,不是字段名
sortField "[]" 同上
type 1 基础模型
pageSize 20
authorId 整数 必传,否则 code=-1
authorName 字符串 必传,否则 code=-1

authorId/authorName 从 token 的 JWT payload 里取(userId/username)。

3.7b POST /model/updateProperty ✅ — 更新模型

改模型字段(含别名)用这个。参数与 addModel 相同,外加 id(模型 id):

参数 说明
id 模型 id(必传)
modelName / modelAlias / fieldList / searchField / sortField / type / pageSize addModel
authorId / authorName 必传

⚠️ 端点选择有坑(实测)

端点 结果
POST /model/updateProperty code=200
POST /model/updateFields ❌ HTTP 400
POST /model/updateFieldList ❌ HTTP 500

名字最贴切的 updateFieldList(摘要「修改FieldList内容字段」)反而不能用。 工具:fix_field_alias.py

3.8 PUT /column/addColumn

创建栏目。要求 modelId 指向的模型已存在,否则 code=205 模型不存在

参数(form body):

参数 说明
type 0/1 0 分级栏目(仅目录,无内容表)/1 内容栏目
parentId 整数 父栏目 id;-1 表示无父级
tag 字符串 全局唯一,同步 OAuth permissionName
title 字符串 栏目名
content 字符串 说明
state 0 0 开启 / 1 关闭 / 2 销毁
level 0 开放
modelId 整数 基础模型 id
modelName 字符串 模型名
authorId / authorName 必传

副作用

  1. DMS 把基础模型(type=1)克隆为栏目模型(type=2),字段自动加 c_ 前缀
  2. 生成物理表 column_{栏目模型名}
  3. 联动 OAuth 注册权限(Column.tagpermissionName

幂等做法:先用 getModelByName 查模型是否存在,存在则跳过整个流程。 参考实现 create_dms_columns.py


4. 迁移阶段将用到的接口 📄

⚠️ 以下均未实测。 参数来自 SKILL.md / Apifox,OpenAPI 未描述(这些接口用 @RequestBody,服务端规范抓不到)。首次使用前请先在测试栏目验证。

4.1 POST /content/selectContentList 📄 — 列表查询(最常用)

columnId=123&page=0&pageSize=20&search=[...]&orderBy=[...]&states=3

返回 content.data(数组)+ content.count(总数)。

count 是行数核对(校验标准 C1)的基准值。 ⚠️ states 过滤会影响 count —— 核对时不要带 states,否则会误判"少了数据"。

search 格式:

[{"field":"c_title","searchType":2,"content":{"value":"政策"}}]
searchType 含义
1 精确
2 模糊
3 区间(start/end)
4 in 数组
5 between

orderBy 格式:

[{"field":"c_created_at","orderByType":2}]

orderByType1 升序,2 降序。

states(发布状态):

0 草稿 · 1 待审 · 2 审完 · 3 发布 · 4 销毁 · 5 退回

多个用逗号:states=2,3。指定 3 则为发布态。

4.2 POST /content/selectContentListInfo 📄 — 综合查询(详情)

selectContentList 参数,额外做字典解析(把 check/type 等字段的码值翻译成文本)。 排查详情问题时用它。

4.3 POST /content/selectContentById 📄 — 单条查询

columnId=123&contentId={uuid}

contentIdUUID 字符串,不是数字 id。

4.4 POST /content/addContent 📄 — 新增

参数 说明
columnId 栏目 id
modelId 栏目模型 id(type=2 的那个)
content JSON 字符串,字段用 c_ 前缀
curl -s -X POST "http://${DMS_HOST}/dms/content/addContent" \
  -H "token: ${DMS_TOKEN}" \
  -d 'columnId=1885' \
  -d 'modelId=2030' \
  -d 'content={"c_id":1,"c_business_code":"abc"}'

4.5 POST /content/updateContent 📄 — 修改

参数同 addContentcontent必须带 id(记录 uuid)。

4.6 DELETE /content/delContentById 📄 — 删除

服务端 OpenAPI 确认存在DELETE /content/delContentById,摘要「删除内容」), 但参数未文档化,Apifox 也未收录。 在生产栏目用之前,先在测试栏目确认它对 columnId/contentId 的确切要求。

4.7 POST /content/importJSON 📄 — JSON 批量导入

服务端 OpenAPI 确认存在(POST/PUT/GET/DELETE 都注册了), 但参数未文档化。大批量迁移可能比逐条 addContent 快得多,值得优先验证

4.8 POST /content/importBeautifiedExcel 📄 — Excel 导入

multipart/form-datafilecolumnIdparseArraytitleParamcontentParam

4.9 POST /file/uploadFile 📄 — 附件上传

multipart/form-datacolumnIdcontentIdparaNametypefiletype0 图 · 1 音 · 2 视 · 3 文件。


5. 建栏目实战(实测契约)

这几条是本次踩出来的,SKILL.md 与 Apifox 都没有。详见 DMS_MAPPING.md §5。

5.1 fieldList 格式

外层是 dict,值是转义后的 JSON 字符串(fastjson 紧凑输出,无空格):

{
  "credit_code": "{\"name\":\"credit_code\",\"alias\":\"统一社会信用代码\",\"must\":true,\"index\":0,\"sequence\":0,\"customType\":\"\",\"describe\":\"\",\"defaultValue\":\"\",\"type\":\"text\",\"frontType\":\"varchar\",\"searchType\":\"1\",\"showParam\":\"name,alias,desc,type,front_type,must,default_value\"}"
}

字段属性:

属性 要求
name 不加 c_ 前缀 —— DMS 克隆时才加。自己加会变成 c_c_xxx
index 必须有,从 0
sequence 0
type DMS 类型(text/integer/double/boolean/timestamp/file…)
frontType 不是 "content" —— 取 §3.6 基础字段表的 name
id 新格式不需要
must 是否必填

5.2 PG → DMS 类型映射

PG 类型 type frontType 状态
character varying / character text varchar ✅ 实测
text text text ✅ 实测
jsonb / json text text ✅ 实测(DMS 无原生 JSON,存 text 后不可用 search 检索内部
bigint / integer / smallint integer int_num ✅ 实测
numeric / double precision double float_num ✅ 实测
boolean boolean boolean ✅ 实测
(epoch 秒换算后) timestamp date_time ✅ 实测
check / mcheck 单/多选 📄 未用到,未验证
type / mtype 类别 📄 未用到,未验证
file files 📄 未用到,未验证
geometry 点/线/面 📄 未用到,未验证

customType/defaultValue 传空字符串 ""

5.3 传输方式:必须用 form body

OpenAPI 把 addModel/addColumn 的参数都声明为 query,但:

方式 结果
query string 41 字段的 fieldListHTTP 400(URL 过长)
form body(-d ✅ 正常

结论:大 payload 一律用 form body,忽略 OpenAPI 的 in: query

5.4 错误码触发条件(实测)

code 实测触发条件
-1 参数错误 addModel / addColumn authorId/authorName
205 模型不存在 addColumn 时模型还没建
214 数据错误 frontType 填了 "content" 而非 param 名
② 缺 index
③ fieldList 的 JSON 带空格(非紧凑)
HTTP 400 fieldList 放进了 query string

5.5 建栏目顺序

PUT /model/addModel      建基础模型 (type=1)
   ↓
POST /model/getModelByName  拿 modelId(幂等检查也用它)
   ↓
PUT /column/addColumn    建内容栏目 (type=1),DMS 自动克隆模型 → type=2 + c_ 前缀

不可颠倒 —— addColumn 要求模型已存在。


6. 命令速查

export DMS_HOST=121.43.55.7:10081
export DMS_TOKEN='...'

# 接口规范(排障第一站)
curl -s "http://${DMS_HOST}/dms/v3/api-docs" -H "token: ${DMS_TOKEN}"

# 栏目树
curl -s -X POST "http://${DMS_HOST}/dms/column/getColumnList" -H "token: ${DMS_TOKEN}"

# 模型
curl -s "http://${DMS_HOST}/dms/model/getModelById?modelId=2030" -H "token: ${DMS_TOKEN}"
curl -s "http://${DMS_HOST}/dms/model/getModelListByPage?type=2" -H "token: ${DMS_TOKEN}"

# 基础字段库(frontType 的取值来源)
curl -s -X POST "http://${DMS_HOST}/dms/param/selectAll" -H "token: ${DMS_TOKEN}"

# 核对行数(C1 校验)
curl -s -X POST "http://${DMS_HOST}/dms/content/selectContentList" \
  -H "token: ${DMS_TOKEN}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "columnId=1885&page=0&pageSize=1"

7. 相关文档

文档 内容
dms_openapi.json 服务端 OpenAPI 全量(82 端点),最权威
SKILL.md DMS 领域模型与常用流程
apifox-dms.md Apifox 干净版
DMS_MAPPING.md 本项目表→栏目映射 + 踩坑记录
RUNBOOK.md 操作手册

8. 浏览服务器文件目录:POST /file/getFiles

用途:列服务器上某个目录的内容。查「后端把文件存哪了」时用它 —— 这些路径不是 URL,用浏览器/curl 直接访问一律 404(实测)。

8.1 参数只有一个:path(form body)

curl -s -X POST "http://121.43.55.7:10081/dms/file/getFiles"   -H "token: ${DMS_TOKEN}"   --data-urlencode "path=../../../../data/dms/dms_upload/yszs"

⚠️ path 是相对 DMS 进程工作目录(Tomcat 的 bin)的,不是文件系统绝对路径。 传绝对路径(/data/...)不会报错,但会返回「当前文件不是文件夹,无子文件」—— 因为那是相对拼接后并不存在的路径。这是最容易踩的一点。

8.2 相对路径换算(实测)

想要的位置 写成
Tomcat bin(工作目录) .
Tomcat 根(有 webapps*conflogsuploads…) ..
/usr/local ../..
/(根) ../../../..
/data ../../../../data
/data/dms/dms_upload ../../../../data/dms/dms_upload
/data/dms/dms_upload/yszs ../../../../data/dms/dms_upload/yszs

8.3 返回形态

{"code":200,"message":"成功!","content":["../webapps_dms","../logs", ...]}
情况 返回
目录内容 content 是数组,元素是「带前缀的相对路径」
目录为空 没有 content 字段(只有 code/message)—— 别把「字段缺失」当成出错
传的是文件路径 content: ["当前文件不是文件夹,无子文件"](说明它只能列目录,读不了文件内容
参数名写错(dir/directory/filePath…) HTTP 500

8.4 实测到的目录布局(2026-09-17)

/data/dms/
├── dms_upload/          ← DMS 上传根目录
│   ├── photo/    7027 项
│   ├── file/     6324 项
│   ├── video/       3 项
│   ├── other/       1 项
│   ├── yszs/        **空**(营商助手专用,新建未写入)
│   └── *.json    7 个 uuid 命名的 json
└── down_files/

📌 结论:/data/dms/dms_upload/yszsDMS 服务器上的真实目录, 目前没有数据;它既不是 URL,也不能通过 getFiles 读文件内容(只能列目录)。