报表设计器
报表设计器
业务用途
报表设计器用于配置数据报表,将多个图表、表格、统计卡片组合到一个报表页面中。与图表设计器不同,报表是一个聚合视图,可以包含多个子组件,适合做管理看板、数据汇总等场景。
报表配置以 report_json 存入 lc_report 表,其中包含 tableId 用于数据查询。运行时通过 POST /api/report/data/{id} 端点查询数据,最终也走 SchemaService.queryDataList() 引擎。
涉及文件
| 层 | 文件路径 | 说明 |
|---|---|---|
| Controller | backend/src/main/java/com/lowcode/controller/ReportController.java | /api/report 端点 |
| Entity | backend/src/main/java/com/lowcode/entity/LcReport.java | 报表实体(@TableName("lc_report")) |
| Service | backend/src/main/java/com/lowcode/service/ReportService.java | 报表配置 CRUD |
| Service | backend/src/main/java/com/lowcode/service/SchemaService.java | 数据查询(复用动态数据引擎) |
| 前端 | frontend/src/views/designer/report/builder.vue | 报表设计器主界面 |
| 前端 | frontend/src/views/runtime/components/RuntimeReport.vue | 运行时报表渲染 |
| 前端API | frontend/src/api/report.ts | 前端请求封装 |
数据库表
lc_report(报表表)
CREATE TABLE `lc_report` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` BIGINT DEFAULT 1 COMMENT '租户编号',
`app_id` BIGINT COMMENT '应用ID',
`report_name` VARCHAR(100) NOT NULL COMMENT '报表名称',
`report_code` VARCHAR(100) NOT NULL COMMENT '报表编码',
`report_type` VARCHAR(50) DEFAULT 'custom' COMMENT '报表类型(custom/dashboard/table_report/chart_report)',
`report_json` LONGTEXT COMMENT '报表JSON配置',
`status` VARCHAR(20) DEFAULT 'draft' COMMENT '状态',
`remark` VARCHAR(500) COMMENT '备注',
`create_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` VARCHAR(50) COMMENT '创建者',
`update_by` VARCHAR(50) COMMENT '更新者',
`deleted` TINYINT DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报表表';LcReport 实体字段
@TableName("lc_report")
public class LcReport extends BaseEntity {
private Long appId; // 应用ID
private String reportName; // 报表名称
private String reportCode; // 报表编码
private String reportType; // 报表类型: custom / dashboard / table_report / chart_report
private String reportJson; // 报表JSON配置(含 tableId)
private String status; // 状态: draft / published
private String remark; // 备注
}后端实现
端点列表(ReportController -- /api/report)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/report/list?appId= | 获取报表列表(按应用ID) |
| GET | /api/report/{id} | 获取报表详情 |
| POST | /api/report | 创建报表 |
| PUT | /api/report | 更新报表 |
| DELETE | /api/report/{id} | 删除报表 |
| POST | /api/report/data/{id} | 获取报表数据(动态查询关联表) |
获取报表数据 -- getReportData()
报表数据查询从 report_json 中解析 tableId,然后复用 SchemaService.queryDataList():
@PostMapping("/data/{id}")
public Result<Map<String, Object>> getReportData(@PathVariable Long id,
@RequestBody(required = false) Map<String, Object> queryParams) {
LcReport report = reportService.getById(id);
if (report == null) return Result.error("报表不存在");
// 从 reportJson 中解析 tableId
Long tableId = null;
if (report.getReportJson() != null && !report.getReportJson().isEmpty()) {
try {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> config = mapper.readValue(report.getReportJson(), Map.class);
if (config.containsKey("tableId")) {
tableId = Long.parseLong(config.get("tableId").toString());
}
} catch (Exception ignored) {}
}
if (tableId == null) {
Map<String, Object> result = new HashMap<>();
result.put("reportConfig", report.getReportJson());
result.put("data", null);
return Result.success(result);
}
Integer pageNum = 1;
Integer pageSize = 1000;
if (queryParams != null) {
if (queryParams.containsKey("pageNum"))
pageNum = Integer.parseInt(queryParams.get("pageNum").toString());
if (queryParams.containsKey("pageSize"))
pageSize = Integer.parseInt(queryParams.get("pageSize").toString());
}
// 复用 SchemaService 的动态查询引擎
Map<String, Object> data = schemaService.queryDataList(tableId, queryParams, pageNum, pageSize);
Map<String, Object> result = new HashMap<>();
result.put("reportConfig", report.getReportJson());
result.put("reportType", report.getReportType());
result.put("data", data);
return Result.success(result);
}reportJson 中的 tableId
与图表不同,报表的 tableId 不是实体字段,而是嵌在 report_json 配置 JSON 中。getReportData() 会解析 JSON 提取 tableId,再走动态查询引擎。
前端实现
报表设计器界面
frontend/src/views/designer/report/builder.vue 提供:
- 报表基本信息配置(名称、编码、类型)
- 关联数据表选择
- 报表布局配置(行 + 组件栅格,与页面设计器类似)
- 子组件配置(图表、统计卡片、表格等)

前端 API 封装
// frontend/src/api/report.ts
export function getReportList(appId?: number) {
return request.get<any>('/report/list', appId ? { appId } : {})
}
export function getReportDetail(id: number) {
return request.get<any>(`/report/${id}`)
}
export function createReport(data: Partial<ReportVO>) {
return request.post<any>('/report', data)
}
export function updateReport(data: Partial<ReportVO>) {
return request.put<any>('/report', data)
}
export function getReportData(id: number, filters?: Record<string, any>) {
return request.post<any>(`/report/data/${id}`, filters)
}运行时渲染
RuntimeReport.vue 在运行时加载报表数据:
// RuntimeReport.vue 第 112 行
const res = await request.post('/runtime/data', {
reportId: props.config.reportId,
...queryParams
})
操作步骤
- 进入「设计器 -> 报表设计」页面,点击「新建报表」
- 填写报表名称、编码,选择报表类型(custom/dashboard/table_report/chart_report)
- 选择关联数据表
- 配置报表布局:添加行,在行中放置子组件(图表、统计、表格等)
- 配置每个子组件的属性
- 点击「保存」
- 在页面设计器中添加
report类型组件,关联此报表的 ID
常见问题
报表数据查询返回 null
getReportData() 从 report_json 中解析 tableId。如果 JSON 中没有 tableId 字段或格式错误,会返回 data: null。确保保存报表时 report_json 中包含 tableId。
报表和图表的区别
图表(lc_chart)是单一可视化组件,tableId 是实体字段。报表(lc_report)是聚合视图,tableId 嵌在 report_json 中,可包含多个子组件。如果只需一个图表,用图表设计器;如果需要管理看板,用报表设计器。
