报表执行(ReportController)¶
报表执行接口:报表显示(HTML 重定向脚本)/ 报表基本信息 / 报表显示(jrxml,含查询表单参数注入)/ 导出字段列表 / 导出 Excel / 导出 PDF / 查询表单模板 / 报表册下报表列表 / 自定义数据源列信息。
- 接口类型:REST 资源(
@Controller继承AbstractRuntimeController;类级**无**produces声明,方法返回类型为String/Resource/void(写回HttpServletResponse),由@ResponseBody或返回类型为Resource的方法经 Spring Jackson 序列化为 JSON,接口类型按返回类型判定为 REST 资源,据源码) - 基址:
${myapps.context-path.runtime:}/api/runtime - Tag:runtime
公共说明¶
- 鉴权(据源码):类级基址位于
/api/runtime/**,在RestSecurityHandlerInterceptor覆盖范围内。豁免判定按 URI 字面匹配,本控制器有两个端点命中豁免规则—— #3 showJrxmlReport(/api/runtime/{applicationId}/reports/{reportId}/showjrxml):据源码豁免——拦截器uri.endsWith("/showjrxml")命中,无需 accessToken(用于运行时直接渲染报表 HTML)。#9 getCustomColumnsInfos(/api/runtime/getCustomColumnsInfos):据源码豁免——拦截器uri.indexOf("/getCustomColumnsInfos") >= 0命中,无需 accessToken。- 其余端点(
#1/#2/#4/#5/#6/#7/#8):需 accessToken(或 debugToken),可通过 Cookie / 请求头 / query 参数任一方式传递。控制器内getUser()(继承自AbstractRuntimeController)必须能取到非空WebUser,否则在DesUtil.decryptTextByUserId(applicationId, getUser().getId())时即抛 NPE。 - 注:
#3与#9虽然拦截器豁免,但控制器源码仍调用getUser()/DesUtil.decryptTextByUserId(..., getUser().getId())。#3容忍user == null(fallback 用 body 中userid构造临时WebUser);#9不容忍null,实际调用仍需登录态(与 detail.md 中豁免端点同理)。 - 路径变量
{applicationId}/{reportId}:必填,经 DES 加密(按当前执行用户密钥),服务端在方法入口处DesUtil.decryptTextByUserId(applicationId, getUser().getId())与DesUtil.decryptTextByUserId(reportId, getUser().getId())解密。 - 响应结构:本控制器响应**非**统一
Resource直接返回—— #1/#3:返回String(@ResponseBody),分别为 JS 重定向脚本 / HTML 路径字符串或错误消息;#2/#4/#7/#8:返回Resource(与统一Resource结构一致);#5/#6:void,直接写回HttpServletResponse输出流为 Excel/PDF 文件下载(produces = "text/html;charset=UTF-8"),非 JSON;#9:返回List<QueryColumnInfo>(@ResponseBody),直接是数组而非Resource。- 完整规则见各端点小节。
- HTTP 状态码:
#3/#4/#5/#6/#7/#8标注@ResponseStatus(HttpStatus.OK)。
1. 报表显示(重定向脚本)¶
按 reportId 加载报表定义,将报表导出为 HTML 文件得到路径,返回 <script>window.location='<contextPath>';</script> 字符串供前端跳转。reportId 为空时返回字符串 "请指定报表!"。
- 接口类型:REST 资源(返回
String,@ResponseBody) - 请求方式:
@RequestMapping(未限定 method,支持 GET / POST 等所有方法) - 请求路径:
/{applicationId}/reports/{reportId}/show(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/show) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportId | path | string | 是 | 报表id(DES 加密密文) |
请求示例¶
GET /api/runtime/__APPID__/reports/__REPORTID__/show HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:String(非 Resource);Content-Type 由 Spring 内容协商决定(典型为 text/plain 或 text/html)。
成功示例(字符串字面量):
未指定报表示例:
2. 获取报表基本信息¶
按 reportId 加载并返回报表定义(ReportService.doView),reportId 为空时返回 error(500, "请指定报表!", null)。
- 接口类型:REST 资源(返回
Resource) - 请求方式:
GET - 请求路径:
/{applicationId}/reports/{reportId}/info(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/info) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportId | path | string | 是 | 报表id(DES 加密密文) |
请求示例¶
GET /api/runtime/__APPID__/reports/__REPORTID__/info HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:Report,报表定义实体(含 name/dataSourceType/viewId/subReportId/calaculateType 等字段)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"id": "__REPORTID__",
"name": "销售月报",
"dataSourceType": "VIEW",
"viewId": "__VIEWID__"
},
"errors": null
}
失败示例:
3. 报表显示(jrxml,POST 提交查询参数)¶
POST 提交查询参数 JSON body(被注入 ParamsTable),按 reportId 加载报表定义,递归处理子报表,最终生成主报表 HTML 文件路径并返回字符串。注意:
- 本端点据拦截器
uri.endsWith("/showjrxml")豁免,无需 accessToken;但源码也容忍getUser()为null:为空时取 body 中userid构造临时WebUser,并按 body 中domainId(若存在)设置企业域。 -
错误返回字符串前缀:
"msg:请指定报表!"/"msg:已知系统异常!<异常消息>"/"msg:未知系统异常!ExceptionName:<类名>,ExceptionMsg:<消息>"。 -
接口类型:REST 资源(返回
String,@ResponseBody,produces = "text/html;charset=UTF-8") - 请求方式:
POST - 请求路径:
/{applicationId}/reports/{reportId}/showjrxml(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/showjrxml) - 鉴权:否(据源码:拦截器
uri.endsWith("/showjrxml")豁免;但控制器内getUser()为null时 fallback body.userid) - Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文);user==null 时**不解密**(按原值使用) |
| reportId | path | string | 是 | 报表id(DES 加密密文);user==null 时**不解密** |
| content | body | string(JSON) | 否 | 查询参数 JSON;解析出的键值对全部注入 ParamsTable |
| docid | query | string | 否 | 文档Id(DES 加密密文),用于作为打印模板时的表单数据源;user==null 时**不解密**,默认空字符串 |
请求体(可选)¶
JSON 对象,常见字段:userid(无登录态时用作 fallback WebUser id)、domainId(无登录态时设置企业域)、以及各查询表单字段。
请求示例¶
POST /api/runtime/__APPID__/reports/__REPORTID__/showjrxml HTTP/1.1
Content-Type: application/json
{
"startDate": "2026-01-01"
}
响应¶
结构:String(非 Resource),Content-Type: text/html;charset=UTF-8。
成功示例(主报表 HTML 文件路径):
失败示例(字符串字面量):
4. 获取报表导出字段¶
解析报表对应 .jrxml 文件的列头与列明细字段(按 X 坐标对齐),返回导出字段名列表。表头与明细列数不一致或抛 ClassCastException 时返回 success("ok", null)。
- 接口类型:REST 资源(返回
Resource) - 请求方式:
GET - 请求路径:
/{applicationId}/reports/{reportId}/columns(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/columns) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportId | path | string | 是 | 报表id(DES 加密密文) |
请求示例¶
GET /api/runtime/__APPID__/reports/__REPORTID__/columns HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:List<String>,列头文本集合(按 X 坐标排序);表头与明细列数不一致时为 null。
成功示例:
失败示例:
其他失败消息:"已知系统异常!<异常消息>"(CommonException)、"未知系统异常!ExceptionName:<类名>,ExceptionMsg:<消息>"。
5. 报表导出 Excel¶
POST 提交查询参数与 columns 字段列表,按 reportId 加载报表定义,递归处理子报表,生成主报表 Excel 文件并以附件形式下载。produces = "text/html;charset=UTF-8"(实际响应体为 Excel 二进制流)。
- 接口类型:REST 资源(文件下载,二进制响应;返回
void) - 请求方式:
POST - 请求路径:
/{applicationId}/reports/{reportId}/exportexcel(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/exportexcel) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportId | path | string | 是 | 报表id(DES 加密密文) |
| content | body | string(JSON) | 否 | 查询参数 JSON;含可选 columns: List<String>(导出列名过滤) |
请求体(可选)¶
请求示例¶
POST /api/runtime/__APPID__/reports/__REPORTID__/exportexcel HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"columns": ["月份", "销售额"]
}
响应¶
结构:二进制 Excel 文件(.xls)附件下载;不返回 JSON Resource。
- 成功:HTTP 200,
Content-Type: application/x-download; charset=<encoding>,Content-Disposition: attachment; filename="<reportName>.xls"(按USER-AGENT区分 Firefox 与其他),响应体为ActivityRunTimeServiceImpl.doFileDownload(file, outputStream)写出的.xls字节流。 - 失败:源码吞
CommonException/Exception仅e.printStackTrace(),无错误响应体。
6. 报表导出 PDF¶
POST 提交查询参数,按 reportId 加载报表定义,递归处理子报表,生成主报表 PDF 文件并以附件形式下载。produces = "text/html;charset=UTF-8"(实际响应体为 PDF 二进制流)。
- 接口类型:REST 资源(文件下载,二进制响应;返回
void) - 请求方式:
POST - 请求路径:
/{applicationId}/reports/{reportId}/exportpdf(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/exportpdf) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportId | path | string | 是 | 报表id(DES 加密密文) |
| content | body | string(JSON) | 否 | 查询参数 JSON,键值对注入 ParamsTable |
| docid | query/body | string | 否 | 文档Id(无 @RequestParam 注解,Spring 默认按 query 解析;用于作为打印模板时的表单数据源) |
请求示例¶
POST /api/runtime/__APPID__/reports/__REPORTID__/exportpdf?docid=__ENC_DOCID__ HTTP/1.1
Content-Type: application/json
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
{
"domainId": "__DOMAINID__"
}
响应¶
结构:二进制 PDF 文件(.pdf)附件下载;不返回 JSON Resource。
- 成功:HTTP 200,
Content-Type: application/x-download; charset=<encoding>,Content-Disposition: attachment; filename="<reportName>.pdf"(按USER-AGENT区分 Firefox 与其他),响应体为ActivityRunTimeServiceImpl.doFileDownload(file, outputStream)写出的.pdf字节流。 - 失败:源码吞
CommonException/Exception仅e.printStackTrace(),无错误响应体。
7. 获取查询表单模板¶
按 reportId 加载报表定义;按数据源类型(视图数据源 → 视图查询表单;其他 → 报表 dataSourceSearchForm)定位查询表单,生成表单 HTML 模板字符串与字段属性列表。
- 接口类型:REST 资源(返回
Resource) - 请求方式:
GET - 请求路径:
/{applicationId}/reports/{reportId}/searchformtemplate(完整:{runtime-context}/api/runtime/{applicationId}/reports/{reportId}/searchformtemplate) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportId | path | string | 是 | 报表id(DES 加密密文) |
请求示例¶
GET /api/runtime/__APPID__/reports/__REPORTID__/searchformtemplate HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:Map,固定字段:
- fields (List<Map<String,Object>>):查询表单各字段属性列表;
- document (Document):基于查询表单创建的 searchDocument;
- template (String):表单 HTML 模板字符串(含隐藏字段 dy_refreshObj,封装 formid/docid/userid/mapVal);
- style (Object,可选):表单样式(仅当 form.style 非空时存在)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"fields": [{ "name": "startDate", "type": "DATE" }],
"document": { "id": "__DOCID__", "formid": "__FORMID__" },
"template": "<input type=\"hidden\" id=\"dy_refreshObj\" formid=\"__FORMID__\" ... />"
},
"errors": null
}
失败示例:
8. 获取当前报表册下的报表¶
按 reportGroupId 加载报表册,按 reportGroup.reportIds(以 ; 分隔)逐项加载报表名,组装为 {reportId: reportName} Map 嵌入返回。
- 接口类型:REST 资源(返回
Resource) - 请求方式:
GET - 请求路径:
/{applicationId}/reportgroups/{reportGroupId}/reports(完整:{runtime-context}/api/runtime/{applicationId}/reportgroups/{reportGroupId}/reports) - 鉴权:是(需 accessToken,据源码)
- Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| applicationId | path | string | 是 | 软件id(DES 加密密文) |
| reportGroupId | path | string | 是 | 报表册id(明文,源码未对该变量做 DES 解密) |
请求示例¶
GET /api/runtime/__APPID__/reportgroups/__REPORTGROUPID__/reports HTTP/1.1
Cookie: accessToken=eyJhbGciOiJIUzI1NiJ9...
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:JSONObject,固定含 data 字段(Map<String,String>,key 为报表Id、value 为报表名);服务层异常被吞时仅 e.printStackTrace(),返回的 data 字段为空 JSONObject(无 data 内层 key)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"data": {
"__REPORTID1__": "销售月报",
"__REPORTID2__": "库存日报"
}
},
"errors": null
}
说明:源码用
json.put("data", map)后再success("ok", json),故data字段内嵌一层data。
9. 获取报表自定义数据源的列信息¶
按自定义数据源脚本(scriptString)解析返回列信息列表。本端点据拦截器 uri.indexOf("/getCustomColumnsInfos") >= 0 豁免,无需 accessToken;但控制器内 getUser() 不容忍 null,实际调用仍需登录态。
- 接口类型:REST 资源(返回
List<QueryColumnInfo>,@ResponseBody;直接数组而非Resource包装) - 请求方式:
POST - 请求路径:
/getCustomColumnsInfos(完整:{runtime-context}/api/runtime/getCustomColumnsInfos) - 鉴权:否(据源码:拦截器
uri.indexOf("/getCustomColumnsInfos") >= 0豁免;但控制器内仍需getUser()非空) - Tag:runtime
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| scriptString | body | string | 是 | 自定义数据源脚本字符串 |
| applicationId | query | string | 否 | 软件id(DES 加密密文);无 @RequestParam 注解,Spring 按 query 参数解析 |
请求示例¶
POST /api/runtime/getCustomColumnsInfos?applicationId=__ENC_APPID__ HTTP/1.1
Content-Type: application/json
"var rows = []; rows.push({name:'字段1', type:'STRING'}); rows;"
响应¶
结构:**非**统一 Resource —— @ResponseBody 直接返回 List<QueryColumnInfo>(JSON 数组),无 errcode/errmsg/data/errors 包裹,据源码如实记录。
成功示例: