1. 页面概览

1.1 是什么

「应用构建」是 LightFoundry 的低代码应用构建器(对应设计文档 TAD-09,对标 Palantir Foundry Workshop,源码 action/web/src/views/AppsPage.vue,约 1047 行)。它让业务人员不写代码、通过点选组件 + 声明式 JSON 绑定来搭建面向对象的数据应用:左侧点选组件类型,中间编辑「组件配置(DataBinding JSON)」,右侧实时预览(<component :is> 动态渲染 table / object_detail / metric_card / button / text 等组件,组件数据经 POST /apps/:id/pages/:pageId/components/:compId/data 加载)。

页面顶部注释块给出了关键架构说明:

数据模型三层:Application(应用)→ AppPage(页面)→ AppComponent(组件实例)。应用定义为 JSON 配置(DataBinding / ActionBinding / StyleConfig 存 PostgreSQL jsonb 或 SQLite TEXT),前端按 JSON 配置运行时渲染。也就是说,「做应用」的本质是配置一份份 JSON:应用是容器,页面是布局,组件是数据视图。

1.2 核心价值

维度说明
零代码建模应用/页面/组件全部通过表单 + JSON 配置完成,不写 Vue 代码
声明式数据绑定DataBinding JSON 声明「取什么对象、过滤什么、排序什么」,后端负责翻译执行
即时预览右侧预览区实时渲染组件,数据直接来自后端语义查询(带 RLS/CLS 只读安全)
对象驱动组件可绑定本体对象类型,数据口径与本体/语义层一致
发布即用应用可发布(draft → published),发布后状态固化
动作扩展按钮/表单组件支持 ActionBinding(action_trigger 模式),可触发本体 Action 写路径

1.3 一句话总结

用「应用 → 页面 → 组件」三层结构 + DataBinding JSON 组装出数据应用,后端语义查询统一取数,前端动态组件实时预览。

2. 访问入口

2.1 路由与菜单

2.2 认证与权限

2.3 端口与 API 前缀

3. 界面布局

页面是三级视图切换的单页应用,view 状态为 list / app / editor,标题随视图变化(viewTitle computed):

┌─────────────────────────────────────────────────────────────────────┐
│  [低代码应用构建器 / 应用页面 · xxx / 页面编辑器 · xxx]  [返回][发布应用]│
├─────────────────────────────────────────────────────────────────────┤
│ View1 list(应用列表):                                               │
│  ┌ 卡片: 创建应用(api_name* | 显示名称* | 分类下拉 | [创建])──────┐  │
│  │        描述输入                                               │  │
│  ┌ 卡片: 应用列表(app-grid 卡片墙)──────────────────────────────┐  │
│  │  卡片: 显示名 + 状态徽标 / api_name·分类 / 描述                 │  │
│  │        操作: [打开] [发布(未发布时)] [页面] [删除]              │  │
├─────────────────────────────────────────────────────────────────────┤
│ View2 app(应用详情):                                               │
│  ┌ 卡片: 应用信息(显示名/name/分类/状态)────────────────────────┐  │
│  ┌ 卡片: 添加页面(页面名称* | 路径 | 布局下拉 | [添加])─────────┐  │
│  ┌ 卡片: 页面列表(page-row: 名称 + 路径 + 布局标签)─────────────┐  │
│  │        操作: [编辑] [预览] [删除]                              │  │
├─────────────────────────────────────────────────────────────────────┤
│ View3 editor(页面编辑器,三栏布局):                                 │
│  ┌ 左栏(220px): 组件库(palette) ─────────────────────────────────┐  │
│  │  8 个组件类型按钮 + 已添加组件列表(点击选中)                  │  │
│  ├ 中栏(360px): 组件配置 ────────────────────────────────────────┤  │
│  │  组件类型下拉 | 标题* | 绑定对象类型下拉 | DataBinding JSON     │  │
│  │  ActionBinding JSON | [保存配置/创建组件] [删除组件]            │  │
│  ├ 右栏(自适应): 预览 ───────────────────────────────────────────┤  │
│  │  [刷新数据] + <component :is> 动态渲染各组件                  │  │
└─────────────────────────────────────────────────────────────────────┘
板块职责
页面头标题随视图变化;非 list 显示「返回」;editor 视图显示「发布应用」
操作结果提示顶部 alert 显示操作结果,可点「关闭」清除
创建应用表单填 api_name/显示名称/分类/描述创建应用
应用卡片墙展示全部应用,行内「打开」「发布」「页面」「删除」
应用信息卡片当前应用元信息
添加页面表单为当前应用添加页面(名称/路径/布局)
页面列表当前应用的页面,行内「编辑」「预览」「删除」
组件库面板8 类组件按钮,点击添加;已添加组件列表供选中
组件配置面板编辑选中组件的类型/标题/对象绑定/DataBinding/ActionBinding
预览面板按组件类型动态渲染数据结果,实时刷新

4. 交互元素详解

4.1 页面级元素

元素位置含义操作效果
「返回」按钮页面头(非 list 视图)返回上一级goBack():editor → app(刷新页面列表);app → list(清空 appDetail 并刷新应用列表)
「发布应用」按钮页面头(editor 视图)发布当前应用publishApp(appDetail);已发布时按钮文字变「已发布」并禁用
操作结果提示页面顶部显示成功/失败提示点「关闭」清空 alert.message

4.2 View1 应用列表

4.2.1 创建应用表单

四列栅格 + 下方描述输入:

元素含义必填默认值操作效果后端调用
「api_name *」应用唯一标识,小写字母/数字/下划线,如 order_ops校验非空组装到 body
「显示名称 *」展示名,如「订单运营」校验非空display_name
「分类」下拉运营/分析/审批/其他运营选择分类category
「描述」应用用途说明-description
按钮「创建」提交--createApp():校验 api_name 与显示名称必填 → POST → 成功清空表单并刷新POST /api/v1/apps

4.2.2 应用列表卡片墙

每张卡片(app-card)包含:显示名 + 状态徽标(statusLabel:draft=草稿/published=已发布/archived=已归档)、api_name: xxx · 分类:xxx、描述(无则「无描述」)。

按钮含义操作效果后端调用
「打开」进入应用详情openApp(app):设 appDetail、view=app、刷新页面列表GET /api/v1/apps/:id/pages
「发布」(未发布时显示)发布应用publishApp(app)POST /api/v1/apps/:id/publish
「页面」进入应用详情(同「打开」)openApp(app)同上
「删除」删除应用confirm(文案「确认删除应用「xxx」?其页面与组件将一并删除。」)→ DELETE /api/v1/apps/:id级联删页面/组件

空列表显示「暂无应用,先创建一个吧。」

4.3 View2 应用详情

4.3.1 添加页面表单

元素含义必填默认值操作效果后端调用
「页面名称 *」页面名,如「概览」校验非空name
「路径」页面路由路径/-path
「布局」下拉grid/tabs/sidebargrid选择布局layout_type
按钮「添加」提交--createPage()POST /api/v1/apps/:id/pages

4.3.2 页面列表

每行(page-row):页面名 + 路径(灰色 page-path)+ 布局标签(status-tag status-draft)。

按钮含义操作效果后端调用
「编辑」进入编辑器openPage(page):view=editor,并行加载组件与对象类型GET .../components + GET /api/v1/ontology/objects
「预览」进入编辑器预览同「编辑」同上
「删除」删除页面confirm(「确认删除页面「xxx」?其组件将一并删除。」)DELETE /api/v1/apps/:id/pages/:pageId

空列表显示「暂无页面,添加一个页面开始搭建应用。」

4.4 View3 页面编辑器

4.4.1 组件库(左栏)

元素含义操作效果后端调用
「表格」(table,☰)对象列表表格addComponent('table')POST .../components
「对象详情」(object_detail,⧉)单个对象全部属性addComponent('object_detail')同上
「指标卡」(metric_card,#️⃣)大数字指标addComponent('metric_card')同上
「图表」(chart,📈)图表(MVP 预览占位)addComponent('chart')同上
「按钮」(button,🔘)触发动作addComponent('button')同上
「筛选栏」(filter_bar,⌕)动态筛选(MVP 预览占位)addComponent('filter_bar')同上
「表单」(form,✎)收集输入提交(MVP 预览占位)addComponent('form')同上
「文本」(text,T)静态内容addComponent('text')同上

点击任意组件按钮:busy 期间禁用;POST 创建组件(title 自动取组件类型中文标签,data_binding: {}),成功后提示「组件已添加,请在中间面板配置数据绑定」,刷新组件列表并自动选中新建组件。「已添加组件」列表:显示 title || 类型标签 与组件类型英文,点击选中(selectComp)。

4.4.2 组件配置(中栏)

选中组件后表单填充(selectComp 回填),可编辑:

元素含义操作效果后端调用
「组件类型」下拉修改组件类型改变 form.component_type保存时生效
「标题 *」组件显示标题保存时校验非空title
「绑定对象类型(数据源)」下拉绑定本体对象类型(组件数据源)选项来自对象类型列表;「不绑定」= nullobject_type_id
「DataBinding JSON」textarea核心数据绑定配置保存时 JSON 解析校验data_binding
「ActionBinding JSON(可选)」textarea动作绑定(按钮/表单)可选,非空时 JSON 校验action_binding
按钮「保存配置」/「创建组件」提交校验标题必填 + JSON 合法;有 id 走 PUT,无 id 走 POSTPUT/POST .../components[/:compId]
按钮「删除组件」删除当前组件confirm → DELETE → 清空表单并刷新DELETE .../components/:compId

DataBinding JSON 示例(模板 placeholder 逐字):

{"mode":"object_list","properties":["order_id","amount","status"],"filters":[{"field":"order_id","op":"eq","value":"{{selectedRowId}}"}],"page_size":50}

mode 支持 object_list / object_detail / aggregation / static / action_trigger(后端 BindingMode* 常量)。{{...}} 是运行时参数引用,会在加载组件数据时用运行时参数替换(类型保留,未解析参数置 null)。

4.4.3 预览(右栏)

元素含义操作效果后端调用
「刷新数据」按钮重新加载全部组件数据loadAllData() → 逐组件 POST 数据接口POST .../components/:compId/data

预览区每个组件一个 preview-item,点击可选中(联动中栏表单)。渲染器按类型分派(rendererFor):

组件类型渲染行为
tablecolumns 做表头、rows 做行渲染表格;有 error 显示「加载失败:...」;无数据显示「暂无数据(请配置对象绑定与 DataBinding 后刷新)」
object_detailrows[0] 首行,按列名/值渲染详情行;无数据「暂无对象(请配置 object_id 参数后刷新)」
metric_card大号数字显示 rows[0][0](聚合首行首列),缺省
button渲染按钮,点击 window.alert 提示「按钮「xxx」动作待接线:<ActionBinding JSON>」(未配置则「未配置 ActionBinding」)
text显示 style_config.content || title 的静态文本
chart / filter_bar / form占位提示「组件类型 xxx 预览待接入(MVP 支持 table/object_detail/metric_card/button/text)」

5. 后端关联

5.1 API 客户端

5.2 端点表

方法路径请求体要点成功响应备注
GET/apps-{data: [...]}列出应用
POST/appsname/display_name/description/category201 {data:{id}}owner 由服务端注入当前用户
GET/apps/:id-{data:{...}}应用详情(前端未直接用)
PUT/apps/:id同创建{data:{id}}前端未使用
DELETE/apps/:id-{data:{deleted:true,id}}级联页面/组件
POST/apps/:id/publish-{data:{published:true,id}}draft → published
GET/apps/:id/pages-{data:[...]}列出页面
POST/apps/:id/pagesname/path/layout_type201 {data:{id}}添加页面
PUT/apps/:id/pages/:pageId同创建{data:{id}}前端未使用
DELETE/apps/:id/pages/:pageId-{data:{deleted:true,id}}级联组件
GET/apps/:id/pages/:pageId/components-{data:[...]}列出组件
POST/apps/:id/pages/:pageId/componentscomponent_type/title/object_type_id/data_binding201 {data:{id}}添加组件
PUT/apps/:id/pages/:pageId/components/:compId同创建(可含 action_binding){data:{id}}更新组件
DELETE/apps/:id/pages/:pageId/components/:compId-{data:{deleted:true,id}}删除组件
POST/apps/:id/pages/:pageId/components/:compId/data{"params":{...}}{data:{component_id,component_type,title,columns,rows,action?,error?}}加载组件数据
POST/apps/:id/pages/:pageId/data同左{data:[...]}页面联动加载(前端未直接用)

5.3 响应结构

组件数据加载响应示例(table 组件):

{
  "data": {
    "component_id": 3,
    "component_type": "table",
    "title": "订单列表",
    "columns": ["order_id", "amount", "status"],
    "rows": [
      [1001, 2000, "已发货"],
      [1002, 1500, "待审核"]
    ]
  }
}

加载失败时前端把 err.response?.data?.error 存入 dataMap[comp.id].error,预览区渲染「加载失败:<error>」。无绑定的组件(文本/按钮)返回空 columns/rows,预览走各自渲染分支。

5.4 关联模块表

后端包/文件职责
action/products/foundry/apps/models.go三张表:applications / app_pages / app_components;状态/类型常量
action/products/foundry/apps/service.goAppService:应用/页面/组件 CRUD、发布、数据加载(语义查询)、action_trigger
action/products/foundry/server/apps_handlers.goHTTP handler + RegisterAppsRoutes 路由注册
action/products/foundry/server/server.gosetupRouter 中 RegisterAppsRoutes(protected, s)
action/products/foundry/ontology对象类型元数据(绑定下拉 GET /api/v1/ontology/objects
action/products/foundry/semantic + pipeline语义查询与连接器定位真实数据源

5.5 关键机制

6. 核心流程详解

6.1 主流程一:创建应用

  1. 进入页面默认在「应用列表」视图。
  2. 填「api_name」与「显示名称」(必填),选「分类」,可填「描述」。
  3. 点「创建」→ createApp() 校验 → POST /api/v1/apps → 成功提示「应用创建成功」,清空表单并刷新列表。
  4. 新应用出现在卡片墙,状态为草稿(draft)。

6.2 主流程二:添加页面

  1. 在卡片墙点「打开」或「页面」→ 进入「应用详情」视图。
  2. 填「页面名称」(必填)、「路径」(默认 /)、「布局」(grid/tabs/sidebar)。
  3. 点「添加」→ POST /api/v1/apps/:id/pages → 页面列表出现新页面,布局标签显示。

6.3 主流程三:编辑器内组装应用

  1. 在页面列表点「编辑」或「预览」→ 进入「页面编辑器」三栏视图,自动并行加载组件列表与对象类型列表。
  2. 左栏点组件类型按钮 → 自动创建组件并选中,中栏填充表单。
  3. 中栏选「绑定对象类型(数据源)」、写「DataBinding JSON」(如 object_list 模式)、可选「ActionBinding JSON」。
  4. 点「保存配置」(新建时显示「创建组件」)→ PUT/POST 组件接口 → 刷新组件列表与预览数据。
  5. 右栏点「刷新数据」手动重新加载全部组件数据;点击预览区的组件可快速选中。
  6. 保存后组件出现在「已添加组件」列表,预览区实时渲染真实数据。

6.4 主流程四:发布应用

6.5 数据流 / 任务终态语义

用户点击组件类型 ──▶ POST components ──▶ 组件落库(component_type/title/data_binding)
      │
      ▼
选中组件 → 中栏表单回填 → 编辑 DataBinding JSON
      │
      ▼
保存配置(PUT/POST) ──▶ fetchComponents ──▶ loadAllData
                                            │
            ┌───────────────────────────────┤
            ▼                               ▼
  POST components/:compId/data      (逐组件并行)
            │
            ▼
  resolveBindingParams({{selectedRowId}} 等)
            ▼
  mode 分派: object_list / object_detail / aggregation / static / action_trigger
            ▼
  dataMap[comp.id] ──▶ 右栏 <component :is> 渲染

状态机:应用 draft(草稿)→ published(已发布)→ archived(已归档,后端支持、前端无 UI)。组件无独立状态字段,以是否存在为准。组件数据加载是同步 HTTP,无任务轮询。

7. 权限与安全

8. 常见问题与排错

8.1 预览区「加载失败:...」

8.2 DataBinding JSON 格式错误

8.3 组件列表刷新后预览数据消失

8.4 创建应用提示必填却无反应

8.5 应用发布后找不到运行入口

9. 已知缺陷与边界

项目说明
预览组件有限MVP 仅 table/object_detail/metric_card/button/text 有真实渲染,chart/filter_bar/form 为占位提示
布局未生效页面布局 grid/tabs/sidebar 仅为定义字段,编辑器预览未按布局排版(三栏固定)
无拖拽调整组件的 position_x/y、width/height 字段存在但编辑器未提供拖拽调整 UI
发布为状态标记发布仅置状态,无独立运行入口/路由挂载
按钮动作未接线button 组件预览点击仅 window.alert 提示待接线,未真正触发 ActionBinding 执行
ActionBinding 能力action_trigger 模式后端已实现(ExecuteActionTrigger),但当前页面编辑器未提供触发 UI
应用可见性应用列表对所有登录用户可见,无按 owner 过滤/隐藏
无分页应用/页面/组件列表均一次拉全量
组件数据无缓存失效数据在进入页面与点「刷新数据」时加载,无定时刷新
archived 状态后端支持 archived,前端无归档/恢复 UI