跳转至

报表执行(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/#6void,直接写回 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/plaintext/html)。

成功示例(字符串字面量):

<script>window.location='/reports/__REPORTID__/html/xxx.html';</script>

未指定报表示例

请指定报表!


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「统一响应结构」)。 dataReport,报表定义实体(含 name/dataSourceType/viewId/subReportId/calaculateType 等字段)。

成功示例

{
  "errcode": 0,
  "errmsg": "ok",
  "data": {
    "id": "__REPORTID__",
    "name": "销售月报",
    "dataSourceType": "VIEW",
    "viewId": "__VIEWID__"
  },
  "errors": null
}

失败示例

{ "errcode": 500, "errmsg": "请指定报表!", "data": null, "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@ResponseBodyproduces = "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(无登录态时设置企业域)、以及各查询表单字段。

{
  "userid": "__USERID__",
  "domainId": "__DOMAINID__",
  "startDate": "2026-01-01"
}

请求示例

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 文件路径):

/reports/__REPORTID__/html/xxx.html

失败示例(字符串字面量):

msg:请指定报表!

msg:已知系统异常!<异常消息>
msg:未知系统异常!ExceptionName:<类名>,ExceptionMsg:<消息>

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「统一响应结构」)。 dataList<String>,列头文本集合(按 X 坐标排序);表头与明细列数不一致时为 null

成功示例

{
  "errcode": 0,
  "errmsg": "ok",
  "data": ["月份", "销售额", "成本"],
  "errors": null
}

失败示例

{ "errcode": 500, "errmsg": "请指定报表!", "data": null, "errors": 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>(导出列名过滤)
请求体(可选)
{
  "columns": ["月份", "销售额"],
  "domainId": "__DOMAINID__"
}

请求示例

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 / Exceptione.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 / Exceptione.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「统一响应结构」)。 dataMap,固定字段: - 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
}

失败示例

{ "errcode": 500, "errmsg": "<异常信息>", "data": null, "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「统一响应结构」)。 dataJSONObject,固定含 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 包裹,据源码如实记录。

成功示例

[
  { "name": "字段1", "type": "STRING", "alias": "字段1" },
  { "name": "字段2", "type": "NUMBER", "alias": "字段2" }
]