页面设计器
页面设计器
业务用途
页面设计器是低代码引擎的布局层。它将一个页面拆分为多行(row),每行内放置若干组件(component),通过栅格列宽(colSpan,1-24)控制组件占比。设计产物以 page_json 存入 lc_page 表,运行时由 PageRenderer.vue 解析并渲染。
页面设计器是表单设计器和列表设计器的「容器」--表单和列表保存时通过 syncFormToPage() / syncListToPage() 自动生成页面配置。运营也可以直接用页面设计器自由组合多个组件(表单 + 列表 + 图表 + 统计卡片等)到一个页面中。
涉及文件
| 层 | 文件路径 | 说明 |
|---|---|---|
| Controller | backend/src/main/java/com/lowcode/controller/PageController.java | /api/page 端点 |
| Controller | backend/src/main/java/com/lowcode/controller/RuntimeController.java | GET /api/runtime/page/{pageId} 运行时获取页面配置 |
| Entity | backend/src/main/java/com/lowcode/entity/LcPage.java | 页面实体(@TableName("lc_page")) |
| 前端 | frontend/src/views/designer/page/builder.vue | 页面设计器主界面 |
| 前端 | frontend/src/views/runtime/PageRenderer.vue | 运行时页面渲染器 |
| 前端 | frontend/src/views/runtime/AppRuntime.vue | 应用运行时容器 |
| 前端API | frontend/src/api/page.ts | 前端请求封装 |
数据库表
lc_page(页面配置表)
CREATE TABLE `lc_page` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` BIGINT DEFAULT 1 COMMENT '租户编号',
`app_id` BIGINT NOT NULL COMMENT '应用ID',
`page_name` VARCHAR(100) NOT NULL COMMENT '页面名称',
`page_code` VARCHAR(100) NOT NULL COMMENT '页面编码',
`page_type` VARCHAR(50) DEFAULT 'custom' COMMENT '页面类型(custom/form/list)',
`page_json` LONGTEXT COMMENT '页面JSON配置',
`route_path` VARCHAR(200) COMMENT '路由地址',
`icon` VARCHAR(100) COMMENT '图标',
`sort_order` INT DEFAULT 0 COMMENT '排序',
`status` VARCHAR(20) DEFAULT 'draft' COMMENT '状态(draft/published)',
`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='页面配置表';LcPage 实体字段
@TableName("lc_page")
public class LcPage extends BaseEntity {
private Long appId; // 应用ID
private String pageName; // 页面名称
private String pageCode; // 页面编码
private String pageType; // 页面类型: custom / form / list
private String pageJson; // 页面JSON配置(核心)
private String routePath; // 路由地址
private String icon; // 图标
private Integer sortOrder; // 排序
private String status; // 状态: draft / published
private String remark; // 备注
}pageJson 结构
{
"rows": [
{
"id": 1,
"gutter": 16,
"components": [
{
"id": 1,
"type": "list",
"colSpan": 24,
"config": {
"title": "供应商列表",
"tableId": 10,
"formId": 5,
"listConfig": { ... }
}
}
]
},
{
"id": 2,
"gutter": 16,
"components": [
{
"id": 2,
"type": "chart",
"colSpan": 12,
"config": { "chartId": 3 }
},
{
"id": 3,
"type": "statistic",
"colSpan": 12,
"config": { "tableId": 10, "aggregateType": "count" }
}
]
}
]
}组件类型
type 字段决定运行时渲染哪个组件:form -> RuntimeForm.vue,list -> RuntimeList.vue,chart -> RuntimeChart.vue,report -> RuntimeReport.vue,statistic -> RuntimeStatistic.vue,button -> RuntimeButton.vue,text -> RuntimeText.vue,divider -> RuntimeDivider.vue。
后端实现
端点列表(PageController -- /api/page)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/page/list?appId= | 获取应用下的页面列表 |
| GET | /api/page/{id} | 获取页面详情 |
| POST | /api/page | 创建页面 |
| PUT | /api/page | 更新页面 |
| DELETE | /api/page/{id} | 删除页面 |
| POST | /api/page/save | 保存页面(新增或更新) |
运行时获取页面配置(RuntimeController)
@GetMapping("/page/{pageId}")
public Result<Map<String, Object>> getPageConfig(@PathVariable Long pageId) {
LcPage page = pageService.getById(pageId);
if (page == null) return Result.error("页面不存在");
Map<String, Object> result = new HashMap<>();
result.put("page", page);
if (page.getPageJson() != null) {
result.put("pageConfig", page.getPageJson());
}
return Result.success(result);
}前端实现
页面设计器界面
frontend/src/views/designer/page/builder.vue 提供:
- 左侧:组件面板(表单、列表、图表、统计、文本、分割线、按钮等)
- 中间:画布区域(行 + 栅格列布局,拖拽组件到列中)
- 右侧:属性面板(页面名称、编码、路由、组件属性配置)

前端 API 封装
// frontend/src/api/page.ts
export function getPageList(appId: number) {
return request.get<any>('/page/list', { params: { appId } })
}
export function getPageDetail(id: number) {
return request.get<any>(`/page/${id}`)
}
export function savePage(data: PageSaveDTO) {
return request.post<any>('/page/save', data)
}运行时渲染
AppRuntime.vue 加载应用菜单和页面,PageRenderer.vue 解析 pageJson 并渲染组件:
// AppRuntime.vue 第 365 行 -- 加载菜单树
const menuRes = await request.get(`/app-menu/tree`, { params: { appId: appId.value } })
// AppRuntime.vue 第 371 行 -- 加载页面列表
const pageRes = await request.get(`/page/list`, { params: { appId: appId.value } })
// PageRenderer.vue 第 57 行 -- 加载页面配置
const res = await request.get(`/page/${props.pageId}`)前端路由
// frontend/src/router/index.ts
{ path: '/app/:appId', name: 'AppRuntime',
component: () => import('@/views/runtime/AppRuntime.vue') },
{ path: '/app/:appId/page/:pageId',
component: () => import('@/views/runtime/AppRuntime.vue') },访问 http://localhost:3000/app/1 进入应用运行时,访问 http://localhost:3000/app/1/page/5 直接打开指定页面。

操作步骤
- 进入「设计器 -> 页面设计」页面,点击「新建页面」
- 填写页面名称、编码,选择所属应用(
appId) - 从左侧组件面板拖拽组件到画布的行中
- 调整组件的
colSpan(1-24)控制宽度占比 - 在右侧属性面板配置每个组件的属性(如
tableId、formId、chartId等) - 点击「保存」,页面配置存入
lc_page.page_json - 在应用菜单管理中,将菜单关联到此页面
表单/列表自动生成页面
通过表单设计器或列表设计器保存时,会自动调用 syncFormToPage() / syncListToPage() 生成 lc_page 记录。这些自动生成的页面 page_type 分别为 form 和 list,不需要手动用页面设计器创建。页面设计器主要用于自定义组合页面(page_type = custom)。

常见问题
页面保存后运行时看不到
lc_page 的 status 需要为 published 才会在运行时显示。表单/列表同步生成的页面会继承表单/列表的 status,确保发布表单/列表后页面也会变为 published。
组件不显示数据
检查 pageJson 中组件的 config 是否正确设置了关联 ID(tableId / formId / chartId / reportId)。运行时渲染器会根据这些 ID 加载数据。
