文档(DocumentController)¶
提供表单数据(Document)的 CRUD、批量保存/删除、局部更新、表单校验,以及视图子表缓存的增删等能力,是 runtime 模块表单数据域的核心控制器。本控制器所有端点均返回 JSON 资源。
- 接口类型:REST 资源(
@RestController,类级produces = APPLICATION_JSON_VALUE) - 基址:
${myapps.context-path.runtime:}/api/runtime/{applicationId} - Tag:document
公共说明¶
- 鉴权(据源码
RuntimeMvcConfig+RestSecurityHandlerInterceptor):拦截器注册到/api/runtime/**与/api/rest/bpm/**,本控制器路径位于/api/runtime/{applicationId}/...,不在豁免名单(豁免名单仅覆盖/api/runtime/login.*、/api/runtime/dingding/authlogin、/api/runtime/synchronization.*、/runtime/sync/.*等,详见 login.md「公共说明 · 鉴权」)。拦截器对非/rest/路径走Security.getUserIdFromToken(request),未取到再尝试Security.getDebugUserIdFromToken(request),两者皆无则拒绝访问。因此所有端点均需 accessToken(或 debugToken),可通过 Cookie / 请求头 / query 参数任一方式传递。 - 路径变量
{applicationId}:必填,经 DES 加密(按当前执行用户密钥),服务端在方法入口处DesUtil.decryptTextByUserId(applicationId, getUser().getId())解密。 - 其它加密 id:路径与请求体中的
id、parentId、childId、viewId、批量删除数组中的元素等,均按当前执行用户密钥做 DES 加密后传输;服务端逐个解密。请求体中字段值若为加密串也会被DesUtil.decryptTextByUserId还原(见AbstractRuntimeController.getParams())。 - Document 请求体:除 PATCH 与 GET 外,POST/PUT 端点的
@RequestBody为 Document JSON 字符串,由AbstractRuntimeController.prepareDocument()解析。结构如下(字段缺省按需传入):{ "id": "<文档Id,DES 加密密文;新建可空>", "formId": "<表单Id,必填>", "viewId": "<视图Id,可选>", "stateId": "<流程实例Id,可选>", "parentId": "<父文档Id,DES 加密密文,可选>", "sign": "<签名,可选>", "isRelate": "<是否关联父文档:'true'/'false',可选>", "items": { "<字段名>": "<字段值>" }, "subDocuments": [ { "...": "嵌套子文档,结构同上" } ], "delete": false, "edit": false, "exparams": { "<额外参数名>": "<值>" }formId用于加载表单定义;items为字段名到字段值的映射(选项类字段的显示值会在服务端转换为存储值)。 - 响应结构:统一
Resource(见 ../index.md「统一响应结构」),字段为errcode/errmsg/data/errors。Resource.data的类型见各端点说明。 - 分页响应:
GET /documents走successWithPagination,Resource.data为JSONObject,结构为: (上述字段名page/page_lines/row_count与底层DataPackage的pageNo/linesPerPage/rowCount不同,以控制器实际响应为准。) - HTTP 状态码:成功默认 200;其中
POST /documents与POST /documents/withoutValid类级标注@ResponseStatus(HttpStatus.CREATED),正常返回 HTTP 201。业务错误由响应体errcode体现(错误码表见 ../index.md)。ResourceNotFoundException→ HTTP 404;Exception/OBPMValidateException→ HTTP 500;MethodArgumentTypeMismatchException→ HTTP 406(errcode=40035);PathNotFoundException(JsonPath 解析失败)→ HTTP 406(errcode=406)。
1. 获取文档¶
根据文档 Id 获取单个文档对象。文档不存在时抛 ResourceNotFoundException,由全局异常处理器返回 404。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/documents/{id}(完整:{runtime-context}/api/runtime/{applicationId}/documents/{id}) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| id | path | string | 是 | 文档Id(DES 加密密文) |
请求示例¶
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:Document,文档对象(含字段值、子文档、流程状态引用等)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"id": "__DOCID__",
"formid": "form-001",
"applicationid": "app-001",
"items": [{ "name": "金额", "value": "1200.00" }],
"state": null,
"subDocuments": []
},
"errors": null
}
失败示例(文档不存在):
2. 创建文档(带校验)¶
新建文档并执行表单校验;校验通过后落库,并处理嵌套子文档的增删改。校验失败返回 errcode=4001。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/documents(完整:{runtime-context}/api/runtime/{applicationId}/documents) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| content | body | string(Document) | 是 | Document JSON 字符串(结构见本页「公共说明 · Document 请求体」) |
请求示例¶
POST /api/runtime/__APPID__/documents HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"formId": "__FORMID__",
"items": {
"金额": "1200.00",
"事由": "客户拜访"
}
}
响应¶
结构:统一 Resource。
data:Document,保存后的文档对象(含服务端生成的 id、重计算后的字段值等)。HTTP 状态码为 201(@ResponseStatus(CREATED))。
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": { "id": "__NEWDOCID__", "formid": "__FORMID__", "items": [] },
"errors": null
}
失败示例(表单校验不通过):
{
"errcode": 4001,
"errmsg": "表单校验不通过",
"data": null,
"errors": [
{ "errcode": 40001, "errmsg": "金额不能为空", "field": "金额" }
]
}
失败示例(服务端异常):
3. 创建文档(不校验)¶
新建文档但不执行表单校验,直接落库;同样会处理嵌套子文档的增删改。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/documents/withoutValid(完整:{runtime-context}/api/runtime/{applicationId}/documents/withoutValid) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| content | body | string(Document) | 是 | Document JSON 字符串(结构见本页「公共说明 · Document 请求体」) |
请求示例¶
POST /api/runtime/__APPID__/documents/withoutValid HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"formId": "__FORMID__",
"items": { "金额": "1200.00" }
}
响应¶
结构:统一 Resource。
data:Document,保存后的文档对象。HTTP 状态码为 201。
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": { "id": "__NEWDOCID__", "formid": "__FORMID__" },
"errors": null
}
失败示例(服务端异常):
4. 更新文档(不校验)¶
更新已有文档,不执行表单校验。会同步处理嵌套子文档的增删改,并校正失效的流程实例引用。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/documents/{id}/withoutValid(完整:{runtime-context}/api/runtime/{applicationId}/documents/{id}/withoutValid) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| id | path | string | 是 | 文档Id(仅用于路由匹配;实际更新目标以请求体内的 id 为准) |
| content | body | string(Document) | 是 | Document JSON 字符串(结构见本页「公共说明 · Document 请求体」) |
请求示例¶
PUT /api/runtime/__APPID__/documents/__DOCID__/withoutValid HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"id": "__DOCID__",
"formId": "__FORMID__",
"items": { "金额": "1500.00" }
}
响应¶
结构:统一 Resource。
data:Document,更新后的文档对象。
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": { "id": "__DOCID__", "formid": "__FORMID__" },
"errors": null
}
失败示例(异常被包装为校验失败):
{
"errcode": 4001,
"errmsg": "文档校验不通过",
"data": null,
"errors": [
{ "errcode": 40001, "errmsg": "<异常信息>", "field": "" }
]
}
说明:服务端捕获异常后统一以
errcode=4001「文档校验不通过」返回,errors[0].errmsg承载实际异常描述(如 OBPMValidateException 校验信息、字段超长Data too long for column等)。
5. 更新文档(带校验)¶
更新已有文档,先执行表单校验(含子表单逐条校验),通过后落库并校正流程实例引用。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/documents/{id}(完整:{runtime-context}/api/runtime/{applicationId}/documents/{id}) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| id | path | string | 是 | 文档Id(仅用于路由匹配;实际更新目标以请求体内的 id 为准) |
| content | body | string(Document) | 是 | Document JSON 字符串(结构见本页「公共说明 · Document 请求体」) |
请求示例¶
PUT /api/runtime/__APPID__/documents/__DOCID__ HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"id": "__DOCID__",
"formId": "__FORMID__",
"items": { "金额": "1500.00" }
}
响应¶
结构:统一 Resource。
data:Document,更新后的文档对象。
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": { "id": "__DOCID__", "formid": "__FORMID__" },
"errors": null
}
失败示例(表单校验不通过):
{
"errcode": 4001,
"errmsg": "表单校验不通过",
"data": null,
"errors": [{ "errcode": 40001, "errmsg": "金额必须大于 0", "field": "金额" }]
}
失败示例(子表单校验不通过):
{
"errcode": 4001,
"errmsg": "子表单校验不通过",
"data": null,
"errors": [{ "errcode": 40001, "errmsg": "明细数量不能为空", "field": "数量" }]
}
6. 批量更新文档(带校验)¶
在一次事务内批量更新与删除多个文档:先校验并更新 edit==true && delete!=true 的文档,再删除 delete==true 的文档(避免先删后插导致同 id 重建)。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/documents/batch(完整:{runtime-context}/api/runtime/{applicationId}/documents/batch) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| content | body | string | 是 | 批量请求 JSON 字符串(结构见下) |
请求体¶
{
"data": [
{
"edit": true,
"id": "<文档Id,DES 加密密文>",
"formId": "<表单Id>",
"items": { "<字段名>": "<字段值>" }
},
{
"delete": true,
"id": "<文档Id,DES 加密密文>",
"parentId": "<父文档Id,DES 加密密文,删除子文档时需要>"
}
]
}
服务端通过 JsonPath $.data[?(@.edit == true && @.delete != true)] 提取待更新集合,通过 $.data[?(@.delete == true)] 提取待删除集合。
请求示例¶
POST /api/runtime/__APPID__/documents/batch HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"data": [
{ "edit": true, "id": "__DOCID1__", "formId": "__FORMID__", "items": { "金额": "1500.00" } },
{ "delete": true, "id": "__DOCID2__", "parentId": "__PARENTID__" }
]
}
响应¶
结构:统一 Resource。
data:List<Document>,更新成功的文档集合(被删除的文档不在列表中)。
成功示例:
{
"errcode": 0,
"errmsg": "保存成功",
"data": [
{ "id": "__DOCID1__", "formid": "__FORMID__" }
],
"errors": null
}
失败示例(校验不通过,整体回滚):
{
"errcode": 4001,
"errmsg": "表单校验不通过",
"data": null,
"errors": [{ "errcode": 40001, "errmsg": "<校验错误>", "field": "<字段名>" }]
}
失败示例(异常,整体回滚):
7. 删除文档¶
根据文档 Id 删除单个文档,并从用户私有缓存中清除。
- 接口类型:REST 资源
- 请求方式:
DELETE - 请求路径:
/documents/{id}(完整:{runtime-context}/api/runtime/{applicationId}/documents/{id}) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| id | path | string | 是 | 文档Id(DES 加密密文) |
请求示例¶
DELETE /api/runtime/__APPID__/documents/__DOCID__ HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:统一 Resource。
data:null。
成功示例:
8. 获取文档集合(分页)¶
按过滤条件分页查询文档列表。返回分页封装结构。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/documents(完整:{runtime-context}/api/runtime/{applicationId}/documents) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| content | body | string | 否 | 过滤条件 JSON(整体作为 filter Map 传入);可空 |
| sortby | query/form | string | 否 | 排序字段(源码方法签名未显式标注 @RequestParam,按名称绑定 query/form 均可) |
| order | query/form | string | 否 | 排序方向(升序/降序) |
| _pagelines | query | int | 否 | 每页条数,缺省走平台默认值(Web.DEFAULT_LINES_PER_PAGE) |
说明:分页参数
_pagelines、_page等通过ParamsTable.convertHTTP(request)统一抽取(见AbstractRuntimeController.getParams())。
请求示例¶
GET /api/runtime/__APPID__/documents?sortby=lastModified&order=desc&_pagelines=20 HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
带过滤条件时(body 为过滤 JSON):
GET /api/runtime/__APPID__/documents?_pagelines=20 HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{ "金额": "1200.00" }
响应¶
结构:统一 Resource。
data:分页 JSONObject(见本页「公共说明 · 分页响应」),含 data/page/page_lines/row_count 四个字段。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"data": [
{ "id": "__DOCID1__", "formid": "__FORMID__" },
{ "id": "__DOCID2__", "formid": "__FORMID__" }
],
"page": 1,
"page_lines": 20,
"row_count": 53
},
"errors": null
}
9. 批量删除文档¶
按文档 Id 数组批量删除,并从用户私有缓存中清除。
- 接口类型:REST 资源
- 请求方式:
DELETE - 请求路径:
/documents(完整:{runtime-context}/api/runtime/{applicationId}/documents) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| content | body | string | 是 | DES 加密文档Id 的 JSON 数组字符串 |
请求体¶
请求示例¶
DELETE /api/runtime/__APPID__/documents HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
["__ENC_DOCID1__", "__ENC_DOCID2__"]
响应¶
结构:统一 Resource。
data:null。
成功示例:
10. 更新缓存中子表数据¶
视图子表行编辑场景:将一行子文档暂存到主文档的用户私有缓存(不入库),并返回确认脚本执行结果与变化字段。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/views/{viewId}/documents/{parentId}/childs(完整:{runtime-context}/api/runtime/{applicationId}/views/{viewId}/documents/{parentId}/childs) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| viewId | path | string | 是 | 视图Id(DES 加密密文) |
| parentId | path | string | 是 | 主表文档Id(DES 加密密文) |
| content | body | string(Document) | 是 | 子文档 Document JSON 字符串(结构见本页「公共说明 · Document 请求体」) |
请求示例¶
POST /api/runtime/__APPID__/views/__VIEWID__/documents/__PARENTID__/childs HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"formId": "__SUBFORMID__",
"items": { "数量": "10", "单价": "20.00" }
}
响应¶
结构:统一 Resource。
data:JSONObject,可能的字段:
- type(string,可选):视图「确认活动脚本」返回的 JsMessage.type(如 TYPE_DANGER)。
- content(string,可选):确认脚本返回的提示文案。
- changedField(array,可选):本次相对原值发生变化的字段列表,每个元素为 { "<字段名>": "<新值>" }。
字段缺失时该键不出现。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"type": "danger",
"content": "数量超过上限",
"changedField": [{ "数量": "10" }, { "金额": "200.00" }]
},
"errors": null
}
失败示例(校验不通过):
{
"errcode": 4001,
"errmsg": "校验不通过",
"data": null,
"errors": [{ "errcode": 40001, "errmsg": "<校验错误>", "field": "<字段名>" }]
}
11. 删除缓存中子表数据¶
视图子表行编辑场景:从主文档的用户私有缓存中移除一行子文档,并执行视图「删除活动脚本」。仅作用于缓存,不入库。
- 接口类型:REST 资源
- 请求方式:
DELETE - 请求路径:
/views/{viewId}/documents/{parentId}/childs/{childId}(完整:{runtime-context}/api/runtime/{applicationId}/views/{viewId}/documents/{parentId}/childs/{childId}) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| viewId | path | string | 是 | 视图Id(DES 加密密文) |
| parentId | path | string | 是 | 主表文档Id(DES 加密密文) |
| childId | path | string | 是 | 子文档Id(DES 加密密文) |
请求示例¶
DELETE /api/runtime/__APPID__/views/__VIEWID__/documents/__PARENTID__/childs/__CHILDID__ HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:统一 Resource。
data:null。
成功示例:
12. 校验文档¶
按 Document 请求体执行表单校验,不落库。用于提交前的预校验。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/documents/validate(完整:{runtime-context}/api/runtime/{applicationId}/documents/validate) - 鉴权:是(需 accessToken,据源码)
- Tag:document
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 应用Id(DES 加密密文) |
| content | body | string(Document) | 是 | Document JSON 字符串(结构见本页「公共说明 · Document 请求体」) |
请求示例¶
POST /api/runtime/__APPID__/documents/validate HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"formId": "__FORMID__",
"items": { "金额": "1200.00" }
}
响应¶
结构:统一 Resource。
data:校验通过为 null;不通过时 data=null、errors 携带错误明细(每个错误的 errmsg 已剥离单引号)。
成功示例:
失败示例: