应用页面组装

适用版本:ChengOS v0.1.0+ | 最后核对:2026-08-12 | 来源:crates/cheng-nodes/src/nodes/builtin/uicrates/cheng-nodes/src/nodes/builtin/ui/common/types.rschengflow-ui/src/runtimechengflow-ui/scripts/generate-pages.ts

ChengOS 里的页面不是模板文件,而是工作流的输出:每个 UI 节点描述一个区域,ui/page_root 把它们组装起来,产出 PageLayout JSON,再由运行时渲染。

这层间接正是要点。因为页面是工作流的输出,它的内容可以被计算出来——一张表格的数据可以来自同一张图里的数据库查询节点。

组装方式

ui/top_nav ──────────┐
ui/left_sidebar ─────┤
ui/right_sidebar ────┼──► ui/page_root ──► PageLayout JSON ──► 运行时渲染器
ui/header ───────────┤
ui/content ──────────┤
ui/footer ───────────┘

每个区域节点产出一个配置对象;ui/page_root 在具名输入端口上收集它们并生成布局。没连的区域就不会出现。

节点 区域
ui/page_root 骨架——收集一切,输出 PageLayout
ui/top_nav 顶部导航:Logo、菜单、操作按钮
ui/left_sidebar 左侧导航:菜单项、图标、可折叠
ui/right_sidebar 右侧面板:属性、帮助、上下文信息
ui/header 页头:标题、面包屑、操作、标签页
ui/content 主内容区:区块
ui/footer 页脚:版权、链接、社交
ui/route 路由树中的一个节点
ui/rbac_guard 访问控制——见页面访问控制

页面根节点

ui/page_root 承载页面身份和全局外观:

字段 含义
site_id 该页面属于哪个站点
page_id 运行时加载配置所用的页面标识
page_name 人类可读的名字,用于文档与面包屑
theme light(默认)或 dark
layout_template defaultsidebartopnavblank
logofaviconprimary_color 品牌设置,primary_color 为十六进制,如 #1890ff
output_base_dir 归档根目录,默认 site_archive

归档路径是 {output_base_dir}/{site_id}/pages/{page_id}.json

想要完全没有外框时就选 blank——嵌入式视图或落地页。

内容区块

ui/content 持有一个区块列表。区块被刻意设计得很通用:

{
  "blockType": "table",
  "title": "用户列表",
  "span": 24,
  "config": { "columns": [{ "key": "name", "title": "姓名" }] }
}
字段 含义
blockType cardtableformchartraw_htmliframetabsgrid……
title 可选的区块标题
span 栅格占比,1–24
config 形状由区块类型决定

栅格是 24 列:span: 24 是整宽,span: 12 是一半,span: 8 是三分之一。span 为 0 会被拒绝,而不是被悄悄当成整宽。

ui/content 还接受 padding——一个数字,或详细的 {top, right, bottom, left}——以及 background 背景色。

config 刻意不做类型约束:形状由区块类型决定,因此在运行时新增一种区块类型不需要改后端 schema。

路由

ui/route 节点构成一棵:子路由连到父路由的子节点端口。

字段 含义
path 静态(users)、动态(:id)或通配(*
name 显示在菜单与标题中
icon 菜单图标
meta SEO 与扩展数据——titlerequiresAuthkeywordsdescription
page_workflow_id 渲染该路由页面的工作流
site_id 仅根节点配置;子节点通过子端口继承
output_base_dir 仅根节点,默认 site_archive

路由绑定一个页面工作流:访问该路由会执行那个工作流来渲染页面。路由还可以覆盖布局模板,其优先级高于页面工作流自身的默认值。

路由带有状态——ready(页面工作流已配置且可用)、pending(尚未配置)或 failed(页面工作流执行失败)——因此一个半成品站点仍可导航,其缺口是显式可见的,而不是变成一堆白页。

运行时与构建期

有两个渲染器消费同一份 PageLayout

  • 运行时——chengflow-ui/src/runtime/ 把 PageLayout JSON 渲染成实时页面与区块:一个自带路由、布局和区块组件的微型应用渲染引擎。
  • 构建期——scripts/generate-pages.tspnpm gen:pages)针对后端执行工作流,提取 PageLayout 和路由树,同时写入 public/site_archive/{siteId}/ 以及 pagesroutes 数据表。通过 scripts/pages-config.json 配置。

这正是 pnpm build 需要后端在运行的原因:gen:pages 是它的一部分,而不执行产出页面的那些工作流,它就渲染不出页面。见开发环境搭建

静态生成适合内容不随请求变化的页面,快且可缓存;运行时渲染适合内容取决于「谁在问」的页面。同一个站点里可以两者混用。

实用形态

页面工作流:
  数据源节点 ────────────────► ui/content ──┐
  ui/top_nav ───────────────────────────────┼──► ui/page_root
  ui/left_sidebar ──────────────────────────┘

路由工作流:
  ui/route(根,含 site_id)──► ui/route(子,path ":id")
                    │
                    └── page_workflow_id → 上面那个页面工作流

一个工作流只做一个页面。一个组装三个页面的工作流比三个工作流更难测试,而路由树本身已经提供了组合能力。

下一步

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容