1. 页面概览

1.1 是什么

「本体工作台」是 LightFoundry 数据集成与本体引擎的核心建模页面,对应前端源码 action/web/src/views/FoundryPage.vue,挂载于 Foundry 产品侧边栏(FoundryLayout)的第一个菜单项。页面的职责可以用一句话概括:用对象类型(Object Type)把企业数据"语义化"——把数据源中的基础表建模为本体对象,再在对象上叠加属性(Properties)、关系(Links)与动作(Actions)三层定义,最终形成一个可供语义检索、对象查询(OOL)、指标计算、Action 写路径统一消费的本体模型层。

本体(Ontology)层是 LightFoundry 对标 Palantir Foundry 本体系统的核心。它位于"数据集成"与"应用开发"之间:下层是数据集与数据源(基表、字段),上层是管道、指标、应用、工作流、语义检索等消费方。对象类型定义一旦合入(merged),就会落到真实的数据库表(主表),后续的语义检索、对象查询、Action 执行全部基于这套定义运行。因此本页是 Foundry 一切语义能力的"总入口",也是建模者日常操作最频繁的页面。

页面实现的功能包括四大块:(1)对象类型列表与详情浏览——以表格展示全部对象类型及其状态、版本与三要素数量,点击行进入详情面板;(2)创建对象类型——通过一个含属性/链接/动作三组嵌套行的表单一次性创建完整对象定义;(3)对象定义详情编辑——在选中对象后通过「属性 / 关系 / 动作」三个 Tab 分别进行子定义的增删改,其中属性变更走"创建草稿 → 更新草稿 → 提交评审 → 合入"的版本状态机四连调用;(4)版本状态机操作——创建草稿、提交评审、合入、回滚四个版本级动作,以及合入/回滚前必现的影响分析弹窗。

页面的信息层级非常清晰:顶部是全局操作区(创建对象按钮与结果提示),中部是对象类型列表,底部(选中对象后出现)是详情面板。详情面板内又分为版本操作区(草稿/评审/合入/回滚)、Tab 切换区、以及对应 Tab 的子定义表格与新增表单。

1.2 核心价值

价值点说明
语义建模唯一入口对象类型 + 属性 + 链接 + 动作一次成型,是语义检索/对象查询/指标/管道/应用的公共定义源头
版本状态机治理每次结构变更都经过 draft → review → merged 三态流转,杜绝直接改线上结构;支持审批门禁与回滚
影响分析前置合入、回滚前自动弹出影响分析(链接/动作/管道/血缘/指标/编辑引用),把变更风险显性化
属性变更快速合入属性增删改自动串联四连调用(建草稿→更新→评审→合入),单次操作即产出新 merged 版本
13 类 ValueType属性类型下拉覆盖 text/number/integer/decimal/currency/percentage/date/datetime/bool/enum/json/array<text>/array<number> 冻结枚举,与后端 GET /ontology/value-types 目录一一对应
稳定标识对象 api_name(name)唯一,RID 为 object-type:<api_name>,跨环境、跨库一致,供 YAML 导出/契约引用

1.3 一句话总结

本体工作台是 LightFoundry 的"对象类型建模台":以对象为纲、属性/链接/动作为目,用草稿-评审-合入-回滚的版本状态机保证每一次结构变更都安全、可审计、可回退。

2. 访问入口

2.1 路由与菜单

项目
路由 path/foundry/foundry 布局下的空子路由)
路由 nameFoundry
页面标题Foundry 本体工作台
菜单入口Foundry 侧边栏(action/web/src/views/FoundryLayout.vuemenuItems 第一项):{ path: '/foundry', label: '本体工作台' }
前端源码action/web/src/views/FoundryPage.vue(约 1046 行)
路由注册action/web/src/router/index.js/foundry 布局(component: FoundryLayout,meta.requiresAuth: true),子路由 path: '' 挂 FoundryPage

侧边栏激活高亮规则:isActive('/foundry') 使用精确匹配route.path === '/foundry'),其余子页面按前缀匹配。因此只有正好访问 /foundry 时"本体工作台"才高亮,访问 /foundry/versions 等子页时高亮切到对应子菜单,不会让本体工作台常亮。

访问方式:登录 Foundry(/login 统一登录,token 存 localStorage 的 aip_token)后,点击任意 Foundry 页面侧边栏顶部的「本体工作台」,或直接访问 http://<host>:5173/foundry(开发态 Vite 端口 5173)。

2.2 认证与权限

项目
requiresAuthtrue(路由 meta 声明,未登录访问被路由守卫拦到 /login)
token 类型aip_token(JWT,Bearer 方式),登录后存 localStorage
token 存放 keylocalStorage['aip_token'](用户名列 key 为 aip_username
后端守卫路由全部挂在 protected 分组(JWT authMiddleware),未带 token 或 token 失效返回 401
角色限制页面本身不做角色级细分(对象建模为通用功能),但 Action 的 requires_approval 会触发审批门禁(approve 数不足时合入被拒)
404 排错提示访问 /foundry 报 404 时,先确认 Vite 代理已按产品前缀分流(/api → 18081),并确认 Foundry 后端(foundry/cmd)已启动;若页面白屏但接口 200,多为路由未注册或 FoundryLayout 菜单路径与 router 不一致

2.3 端口与 API 前缀

项目
后端端口18081(Foundry 服务默认端口)
前端 API 前缀/api(Vite 代理将 /api 分流到 18081)
axios baseURL/api/v1(client.js 中 axios.create({ baseURL: '/api/v1', timeout: 30000 })
认证方式Authorization: Bearer <aip_token>

注意与其它产品区分:AIP 前端 API 前缀为 /aip-api(18080)、Apollo 为 /apollo-api(18082)、Gotham 为 /gotham-api(18083)、Swift 为 /swift-api(18084)。本体工作台属于 Foundry,一律使用 /api/v1/... 前缀;若误用其它产品前缀会打到错误后端返回 404。

3. 界面布局

页面整体为单栏纵向布局(FoundryLayout 左侧边栏 + 右侧内容区),本页内容从上到下分为五块。文字框图如下:

┌─────────────────────────────────────────────────────────────┐
│ 页头(page-header)                                          │
│   [Foundry 本体工作台]                    [创建对象]/[收起表单] │
├─────────────────────────────────────────────────────────────┤
│ 操作结果提示(alert)— 加载/创建/保存/合入/回滚的反馈条        │
├─────────────────────────────────────────────────────────────┤
│ 创建对象类型表单(card,默认收起,点「创建对象」展开)          │
│   名称/显示名称/数据源ID/基础表/主键列/多列主键/实现接口/分类/描述 │
│   附加数据源 supplementary_sources(+附加行,≤3)               │
│   属性(+属性行)/ 链接(+链接行)/ 动作(+动作行)三子块       │
│   [创建对象] [取消]                                          │
├─────────────────────────────────────────────────────────────┤
│ 对象类型列表(card)                                          │
│   工具栏:关键字过滤 / 每页条数 ▾ / 第 N/M 页 / 上一页 下一页  │
│   表头:ID | 名称 | 显示名称 | 状态 | 版本 | 属性 | 链接 | 动作 │
│   行:点击选中(row-selected 高亮)                          │
├─────────────────────────────────────────────────────────────┤
│ 详情面板(card,选中对象后出现)                               │
│   标题行:显示名 + 状态徽标 + v版本号 + meta 信息               │
│   版本操作区:[创建草稿][提交评审][合入] [回滚到版本▾][回滚]     │
│   Tab 切换:[属性][关系][动作](默认「属性」)                  │
│   ┌ 属性 Tab:新增属性表单(内联) + 属性表(编辑/删除)           │
│   ┌ 关系 Tab:新增链接表单(内联) + 链接表(删除)                │
│   ┌ 动作 Tab:新增动作表单(内联) + 动作表(删除)                │
└─────────────────────────────────────────────────────────────┘
   └─ 全局覆盖层:影响分析弹窗(modal-overlay + modal-card)

各板块职责:

4. 交互元素详解

4.1 页头区

元素位置含义必填/默认值操作效果触发的后端调用
页面标题「Foundry 本体工作台」页头左侧固定标题,h2无交互
按钮「创建对象」页头右侧展开/收起创建表单点击调用 toggleCreateForm() 翻转 showCreateForm;展开时文案变为「收起表单」无(纯前端显隐)

4.2 操作结果提示条

元素位置含义必填/默认值操作效果触发的后端调用
alert 提示条页头与表单之间全局操作反馈alert.message 空时不渲染;默认 type alert-info展示最近一次操作结果,颜色随 type 变化
「关闭」链接按钮提示条右上角手动关闭提示置空 alert.message

4.3 创建对象类型表单(card)

元素含义必填/默认值操作效果触发的后端调用
输入框「名称(api_name)*」对象类型稳定标识(api_name),唯一索引必填;placeholder 如 order提交时作为 payload.name随创建请求
输入框「显示名称」中文等展示名选填;placeholder 如 订单提交时 display_name随创建请求
输入框「数据源 ID *」对象主表所在数据源必填,type=number,v-model.number,默认 1提交时 data_source_id随创建请求
输入框「基础表」对象映射的基础表名选填;placeholder 如 orders提交时 base_table随创建请求
输入框「主键列」主键列名(简单单主键便捷字段)选填;placeholder 如 id提交时 pk_column随创建请求
输入框「多列主键 pk_columns」复合主键列(对象级高级字段)选填;placeholder「复合主键,逗号分隔(如 tenant_id,id)」逗号/中文逗号分隔解析为数组;非空时提交 pk_columns(空则不提交该字段,保留后端缺省)随创建请求
下拉「实现接口 implements_interfaces」(多选,span 2)声明本对象实现的接口类型(api_name 数组)选填;选项来自 GET /ontology/interfaces(显示「显示名(api_name)」)多选;非空时提交 implements_interfaces。后端 validateImplementsInterfaces 会校验引用的接口须已存在,缺失返回 422随创建请求;选项加载 GET /ontology/interfaces
输入框「分类」对象分类标签选填;placeholder 如 core提交时 category随创建请求
文本域「描述」对象类型描述选填;grid-column: span 3 占满整行提交时 description随创建请求
子块标题「属性」+ 按钮「+ 属性行」属性定义区默认已含 1 行空属性点击 addPropRow() 追加一行属性
属性行输入框「属性名」属性 api_name行内选填(提交时 name 为空的属性行会被过滤)提交时 properties[].name随创建请求
属性行输入框「显示名」属性显示名选填提交时 properties[].display_name随创建请求
属性行下拉「数据类型」属性 ValueType默认 text选项来自 VALUE_TYPE_OPTIONS(13 类冻结枚举,label 带括号值,如「文本(text)」)随创建请求
属性行下拉「共享属性」(第二行,宽度 230px)引用共享属性定义默认「不引用共享属性」;选项来自 GET /ontology/shared-properties(显示「共享:显示名(data_type)」)选中后提交 properties[].shared_property_id;后端 resolveSharedPropertyDefaults 从共享定义复制 data_type/constraints 等默认值并保留引用随创建请求;选项加载 GET /ontology/shared-properties
属性行输入框「单位 unit *」(第二行,仅 currency/percentage 显示)ValueType 联动约束 constraints.unit条件必填:类型为 currency/percentage 时后端 validatePropertyTypeConstraints 强制要求 unit,缺失则 422提交前前端先校验 unit 非空,为空提示「属性"xx"为 <类型> 类型,请填写单位 unit(后端必填约束)」并中断随创建请求(写入 properties[].constraints.unit
属性行输入框「小数位 precision」(第二行,仅 decimal 显示)ValueType 联动约束 constraints.precision选填(type=number);placeholder 如 2非空时提交 properties[].constraints.precision(数值)随创建请求
属性行输入框「映射列」映射到底层表的列选填;为空时后端按 mapped_column || name 兜底为属性名提交时 properties[].mapped_column随创建请求
属性行复选框「PII」是否敏感字段默认 false提交时 properties[].is_pii随创建请求
属性行复选框「主键」是否主键约束字段默认 false提交时 properties[].is_primary_key随创建请求
属性行输入框「同义词」(属性行第二行)属性检索别名;语义检索按 0.7 权重参与匹配选填;字符串原样存,分隔符支持 ASCII 逗号/全角逗号/顿号/竖线/中文分号;placeholder 如 客户,顾客提交时 properties[].synonyms随创建请求
属性行输入框「属性口径说明」(属性行第二行)列级口径/说明,随列存储(NLQ/检索列级上下文)选填;placeholder 如 单位毫秒,均值需排除 NULL 会话提交时 properties[].description随创建请求
属性行按钮「删除」删除该属性行removeRow(createForm.properties, i) 移除行
子块标题「链接」+ 按钮「+ 链接行」关系定义区默认 0 行点击 addLinkRow() 追加一行链接
链接行输入框「链接名」关系 api_name行内选填(提交时 name 为空被过滤)提交时 links[].name随创建请求
链接行下拉「目标对象」链接的目标对象选填;选项来自 objectTypes(显示 name(#id)),首项为禁用的「目标对象」占位提交时 links[].target_object_type_id随创建请求
链接行下拉「基数」关系基数默认 1:N;选项 1:1 / 1:N / N:M提交时 links[].cardinality随创建请求
链接行下拉「方向」关系方向默认 directed;选项 directed / bidirectional / undirected提交时 links[].direction随创建请求
链接行按钮「删除」删除该链接行removeRow(createForm.links, i)
子块标题「附加数据源 supplementary_sources(≤3)」+ 按钮「+ 附加行」附加数据源定义区默认 0 行点击 addSuppRow() 追加一行({data_source_id, table, join_on}
附加行输入框「数据源 ID」补充表所在数据源 id(type=number)行内选填;整行全空时被过滤提交时 supplementary_sources[].data_source_idNumber(...)||0随创建请求
附加行输入框「补充表名」补充表名,placeholder 如 order_items行内选填提交时 supplementary_sources[].table(trim)随创建请求
附加行输入框「关联条件」主表与补充表的 join 条件,placeholder 如 orders.id = order_items.order_id行内选填提交时 supplementary_sources[].join_on(trim)随创建请求
附加行按钮「删除」删除该附加行removeRow(createForm.supplementary_sources, i)
子块标题「动作」+ 按钮「+ 动作行」动作定义区默认 0 行点击 addActionRow() 追加一行动作(基础字段行 + JSON 配置行两行式)
动作行输入框「动作名」动作 api_name行内选填(name 为空被过滤)提交时 actions[].name随创建请求
动作行下拉「编辑类型」Action 写路径类型默认 modify;选项 modify / create / delete / link提交时 actions[].edit_type随创建请求
动作行输入框「param_schema JSON」类型化参数(JSON Schema)选填;placeholder 如 {"type":"object"}提交前逐字段 JSON.parse 校验(param_schema/validation_rules/write_back_config),非法提示「动作"xx"的 xx 不是合法 JSON」并中断随创建请求(解析后对象)
动作行输入框「幂等键字段」从参数取幂等键的字段(如 inventory_id选填提交时 actions[].idempotency_key_field随创建请求
动作行勾选「需审批」requires_approval默认关提交时 actions[].requires_approval(勾选后该对象后续合入触发审批门禁)随创建请求
动作行输入框「validation_rules JSON」提交前校验(JSON 表达式数组)选填;空串按 null非法 JSON 中断随创建请求(解析后对象)
动作行输入框「write_back_config JSON」回写声明(JSON,snake_case:data_source_id/sql_template/optimistic_lock…)选填;空串按 null缺它动作执行后无法回写源数据;复杂结构可创建后在详情「动作」Tab 弹窗编辑随创建请求(解析后对象)
动作行按钮「删除」删除该动作行removeRow(createForm.actions, i)
提交按钮「创建对象」表单底部左侧提交时文案变「提交中...」且禁用(submitting);先校验各动作 param_schema/validation_rules/write_back_config 为合法 JSON,再组装 payload 调创建接口;成功后提示「对象创建成功 id=...」、重置表单并刷新列表POST /ontology/objects
按钮「取消」表单底部右侧resetCreateForm() 重置表单为空并收起

创建对象 payload 组装要点handleCreate):对象级高级字段先组装——pk_columns_textparsePkColumnsText 解析为数组、implements_interfaces 过滤空项、supplementary_sources 过滤全空行(table/join_on/data_source_id 皆为空的整行剔除,data_source_idNumber(...)||0 转数值),三者非空才写入 payload(空则不提交该字段,交由后端缺省);属性行过滤掉 name 为空的行后映射为 {name, display_name, data_type, mapped_column: mapped_column || name, is_pii, is_primary_key, synonyms, description, constraints?, shared_property_id?},其中 constraintsbuildPropConstraints(data_type, enum_text, orig, unit, precision) 按 ValueType 联动组装(enum→constraints.enum;currency/percentage→constraints.unit;decimal→constraints.precision;无剩余键则不提交),shared_property_id 非空才写入;同义词/描述取 trim 后字符串。链接行过滤 name 为空后映射为 {name, target_object_type_id, cardinality, direction};动作行过滤 name 为空后映射为 {name, edit_type, description: description || '', param_schema, validation_rules, write_back_config, idempotency_key_field, requires_approval},其中三个 JSON 字段经 parseOptionalJSON 解析(空串 → null)。提交前先做两道本地校验:动作 JSON 合法性;属性 ValueType 联动约束(enum 需枚举值、currency/percentage 需 unit)。任一不满足时提示并直接 return(不发出请求)。

后端契约CreateObjectTypeRequest 支持 pk_columns / supplementary_sources / implements_interfacesservice_impl.go:196-210,字段定义见 models.go:100-102),属性 PropertyInput 支持 constraints / shared_property_idservice_impl.go applyToModel)。implements_interfacesvalidateImplementsInterfaces 校验(validate.go:105-129),currency/percentage 的 unit 由 validatePropertyTypeConstraints 校验(validate.go:374-403);decimal 的 precision 后端未做强校验(前端按约定录入)。supplementary_sourcesmodels.go:101/service_impl.go:205JSON[]byte透传存储,Go 侧无结构体形状、无 ≤3 校验(其形状 [{"data_source_id":n,"table":"x","join_on":"..."}] 来自设计约定 wiki/design/design_foundry.md:203,非后端强约束);存储路径见 repository.go:746

4.4 对象类型列表(card)

元素含义操作效果触发的后端调用
工具栏过滤框「按名称 / 显示名 / 分类过滤…」已取回列表做内存关键字过滤(名称/显示名/分类,忽略大小写)输入即过滤(keyword),并回到第 1 页;命中 0 条时表体显示「无匹配对象」
工具栏「每页 N 条」下拉(page-size-select)前端每页条数选项 10/20/50/100,默认 20;切换后回到第 1 页
工具栏「第 N / M 页 · 共 X 个对象」分页位置与结果计数关键字过滤时追加「(已过滤,全量 Y)」提示
工具栏「上一页」「下一页」前端翻页到首/末页时对应按钮禁用(page <= 1 / page >= totalPages
工具栏提示「列表接口…无服务端分页…」诚实边界说明静态文案,说明分页为前端实现、接口仍全量拉取
表格(表头 ID/名称/显示名称/状态/版本/属性/链接/动作)当前页对象类型摘要(pagedObjects 切片)每行可点击选中点击调用 selectObject(item):置 selectedId、清空 rollbackVersion、再依次 loadDetail() + loadVersions()
行内「名称」<strong>对象 api_name
行内「状态」status-badge对象状态,颜色随 status-{status} 类(draft 黄 / review 蓝 / merged 绿 / deprecated 灰)
行内「版本」显示 v{{version}}
行内「属性/链接/动作」各层数量计数(property_count / link_count / action_count
行高亮 row-selected选中行底色 #e8f0fe

列表数据来自 GET /ontology/objects,响应 dataObjectTypeSummary 数组,每项结构为 {object_type: {...}, property_count, link_count, action_count}

分页实现口径(重点):该端点limit/offset/page 参数,一次返回全量。前端用 filteredObjects(关键字内存过滤)→ totalPagesceil(过滤后长度 / 每页条数))→ pagedObjectsslice 当前页)三层计算属性完成分页;keyword/pageSize 变化时 watch 回到第 1 页,totalPages 变小(如过滤后)时自动把越界页码回退。因此分页只减少 DOM 渲染量,不减少请求数据量;对象数量非常大时仍会全量拉取。

4.5 详情面板——标题与版本操作区

元素含义必填/默认操作效果触发的后端调用
标题行「显示名/name + 状态徽标 + v版本号」选中对象概要
meta 行name=... · 数据源 #... · 表 ... · 主键 ...,展示 object_type 的关键字段
meta 行扩展有值时追加 · 多列主键 a,bpk_columns)、 · 实现接口 Ia,Ibimplements_interfaces)与 · 附加数据源 N 个supplementary_sources.length
按钮「创建草稿」以最新 merged 快照为底新建 draft 版本提示「草稿已创建 version_id=...」,刷新版本列表POST /ontology/objects/{id}/drafts
按钮「提交评审」把最新 draft 版本推入评审前置:存在 draft 状态版本无 draft 时提示「没有可评审的 draft 版本(请先创建草稿)」;成功提示「版本 vX 已提交评审」POST /ontology/drafts/{id}/review
按钮「合入」(btn-success)把最新 review 版本合入主表前置:存在 review 状态版本无 review 时提示「没有可合入的 review 版本(请先提交评审)」;有则先调影响分析弹「合并前影响分析」,再合入并弹「合入结果(影响分析)」POST /ontology/objects/{id}/impactPOST /ontology/drafts/{id}/merge
下拉「回滚到版本」(rollback-select)选择回滚目标(merged 版本)选项来自 mergedVersions(versions 中 status=merged 的版本,显示 v{{version}}选中后启用「回滚」按钮
按钮「回滚」(btn-danger)从历史 merged 快照重建主表前置:已选回滚版本未选时禁用;点击前 confirm('确定回滚到 vX 吗?将重建主表并生成新版本。'),确认后调用回滚接口并弹「回滚结果(影响分析)」POST /ontology/objects/{id}/rollback(body {target_version}

4.6 Tab 切换

元素含义默认操作效果
Tab「属性」属性子定义管理默认激活(activeTab = 'properties'显示属性表与新增表单
Tab「关系」关系子定义管理未激活显示链接表与新增表单
Tab「动作」动作子定义管理未激活显示动作表与新增/编辑弹窗

Tab 通过 tabs 数组渲染,tab-btn.active 高亮为蓝色下划线式。

4.7 属性 Tab

元素含义必填/默认操作效果触发的后端调用
按钮「新增属性」展开内联属性表单openPropForm() 打开空表单
属性表单输入框「属性名」属性 api_name保存时必填,为空提示「属性名不能为空」编辑态预填原值
属性表单输入框「显示名」显示名选填
属性表单下拉「数据类型」ValueType默认 text,选项同创建表单
属性表单下拉「共享属性」(第二行)引用共享属性定义默认「不引用共享属性」;编辑态回填 prop.constraints/shared_property_id提交时写入 shared_property_id(0 表示不引用)保存四连调用中的 PUT 载荷
属性表单输入框「单位 unit *」(第二行,仅 currency/percentage 显示)constraints.unit条件必填(后端校验)为空时提示「属性"xx"为 <类型> 类型,请填写单位 unit(后端必填约束)」并中断同上
属性表单输入框「小数位 precision」(第二行,仅 decimal 显示)constraints.precision选填提交时写入 constraints.precision同上
属性表单输入框「映射列」映射列选填;为空时 mapped_column || name
属性表单复选框「PII」「主键」标记位默认 false
属性表单输入框「同义词」属性检索别名;语义检索按 0.7 权重参与匹配选填;占整行,字符串原样存,分隔符支持 ASCII 逗号/全角逗号/顿号/竖线/中文分号;placeholder 如 客户,顾客,买家提交时 synonyms(trim)保存四连调用中的 PUT 载荷
属性表单文本域「属性口径说明」列级口径/说明,随列存储选填;占整行,rows=2;placeholder 提示"语义检索按 0.3 权重参与匹配"提交时 description(trim)同上
属性表单按钮「保存」提交属性变更提交时文案变「保存中...」;走 commitPropertyChange 四连调用;成功提示「属性保存成功(已生成新 merged 版本)」,关闭表单并刷新详情与版本POST /ontology/objects/{id}/draftsPUT /ontology/drafts/{versionId}POST /ontology/drafts/{versionId}/reviewPOST /ontology/drafts/{versionId}/merge
属性表单按钮「取消」关闭表单propForm.show = false
属性表(名称[含口径小字]/显示名称/类型/映射列/同义词/PII/主键/操作)当前对象属性列表名称列下展示 description 单行截断(悬停看全量);同义词列单行截断(悬停看全量);类型列在数据类型后追加约束摘要:(枚举 a/b)constraints.enum)、(单位 X)constraints.unit)、(精度 N)constraints.precision)、(共享 #id)shared_property_id
属性行按钮「编辑」预填表单进入编辑态openPropForm(p)
属性行按钮「删除」删除属性confirm('确定删除属性"xx"吗?') 后走 commitPropertyChange;成功提示「属性"xx"已删除」同保存的四连调用(属性列表去掉该项)
属性变更的版本语义(重点):属性 Tab 的保存/删除不走子 CRUD 路由(那是链接/动作的路线),而是统一走版本状态机 commitPropertyChange:先用 detail 当前定义组装完整 payload(对象主字段 + 变更后的属性列表 + 原链接 + 原动作),然后顺序调用 建草稿 → PUT /ontology/drafts/{versionId} 覆盖草稿快照 → 提交评审 → 合入。也就是说,一次属性保存/删除等于快速走完一轮版本状态机,产出新的 merged 版本。这要求当前对象没有阻塞的进行中草稿(详见第 8 章常见问题)。

4.8 关系 Tab

元素含义必填/默认操作效果触发的后端调用
按钮「新增链接」展开/收起内联链接表单展开时文案变「收起」
链接表单输入框「链接名」链接 api_name保存时必填
链接表单下拉「目标对象」目标对象(options 来自 objectTypes)保存时必填
链接表单下拉「基数」默认 1:N,选项 1:1/1:N/N:M
链接表单下拉「方向」默认 directed,选项 directed/bidirectional/undirected
链接表单按钮「保存」创建链接名与目标对象为空提示「链接名与目标对象必填」成功提示「链接创建成功」,刷新详情与版本POST /ontology/links
链接表单按钮「取消」关闭表单linkForm.show = false
链接表(ID/名称/源 → 目标/基数/方向/操作)当前对象关系列表「源 → 目标」列显示 #source → #target
链接行按钮「删除」删除链接confirm('确定删除链接"xx"吗?') 后调删除;成功提示「链接已删除」DELETE /ontology/links/{id}?object_type_id={selectedId}

链接的创建/删除会生成新的 merged 版本(后端 AddLink/DeleteLink 返回 version),刷新后详情与版本列表同步更新。

4.9 动作 Tab

动作的新增与编辑共用同一个弹窗.modal-card.action-modal),覆盖动作四大配置块(param_schema / validation_rules / write_back_config / idempotency_key_field / requires_approval)——只有 param_schema 时动作执行后无法回写源数据。

元素含义必填/默认操作效果触发的后端调用
按钮「新增动作」打开动作弹窗(空表单)openActionForm()
动作弹窗输入框「动作名(api_name)」动作 api_name保存时必填,为空提示「动作名必填」
动作弹窗下拉「编辑类型」默认 modify,选项 modify/create/delete/link
动作弹窗输入框「幂等键字段」从参数取幂等键的字段(如 inventory_id选填
动作弹窗勾选「需审批(requires_approval)」动作执行是否需审批默认关勾选后该对象提交评审后合入触发审批门禁(本页暂无 Approve 入口,走接口/后续页面)
动作弹窗文本域「描述」description选填
动作弹窗文本域「param_schema」参数契约(JSON Schema)选填;空串按 null三个 JSON 字段(param_schema/validation_rules/write_back_config)均前端 try parse,非法提示「xx 不是合法 JSON」并中断
动作弹窗文本域「validation_rules」提交前校验(JSON 表达式数组)选填;空串按 null
动作弹窗文本域「write_back_config」回写声明(JSON,字段为 snake_case:data_source_id/sql_template/optimistic_lock/mode…,对齐写路径解析)选填;空串按 null缺它动作执行后无法写回源数据
动作弹窗按钮「保存」新增创建、编辑更新成功提示「动作创建成功 / 动作已更新」,刷新详情与版本新增 POST /ontology/actions;编辑 PUT /ontology/actions/{id}?object_type_id={selectedId}
动作弹窗按钮「取消/关闭」关闭弹窗actionForm.show = false(点遮罩 @click.self 亦可)
动作表(ID/名称/编辑类型/参数 Schema/校验/回写/幂等键/审批/操作)当前对象动作列表校验列 validationSummary()、回写列 writeBackSummary()ds#N · pre/post)、幂等列字段值、审批列是/否;参数 Schema 列以 <code> 展示 JSON
动作行按钮「编辑」编辑该动作(可补写回配置)openActionForm(a) 回填原值(JSON 字段还原为缩进文本)见上方「保存」编辑分支
动作行按钮「删除」删除动作(硬删,无回收站;删除后名字可复用)confirm('确定删除动作"xx"吗?') 后调删除;成功提示「动作已删除」DELETE /ontology/actions/{id}?object_type_id={selectedId}

4.10 影响分析弹窗(modal)

元素含义操作效果
半透明遮罩(modal-overlay)覆盖全屏,z-index: 1000点击遮罩空白处(@click.self)关闭
弹窗标题(impactModal.title如「合并前影响分析」「合入结果(影响分析)」「回滚结果(影响分析)」
「关闭」链接按钮手动关闭impactModal.visible = false
<pre class="code-block">影响分析报告 JSON 原文JSON.stringify(data, null, 2)max-height: 400px; overflow-y: auto 内部滚动

弹窗在三种场景出现:合入前(先单独调 POST /ontology/objects/{id}/impact 弹「合并前影响分析」)、合入后(merge 返回的 impact 字段弹「合入结果(影响分析)」)、回滚后(rollback 返回的 impact 弹「回滚结果(影响分析)」)。

5. 后端关联

5.1 API 客户端

本页使用通用客户端 action/web/src/api/client.js(默认导出 apiClient):

项目
创建方式axios.create({ baseURL: '/api/v1', timeout: 30000 })
默认请求头Content-Type: application/json
请求拦截器localStorage.getItem('aip_token') 取 token,有则注入 Authorization: Bearer <token>
响应拦截器响应状态 401 时:清除 aip_tokenaip_username,若当前路径非 /loginwindow.location.href = '/login' 跳转登录页
超时30000ms(30 秒)
错误取词页面统一用 err.response?.data?.error || err.message 展示后端错误码详情

5.2 端点表(本体工作台实际调用)

方法路径请求体/参数页面触发点成功响应 data
GET/ontology/objectsquery status(本页不带;无 limit/offset/page 参数,一次返回全量页面加载(onMounted fetchObjects)、创建对象后刷新[{object_type, property_count, link_count, action_count}]
POST/ontology/objects对象完整定义(见 4.3 payload)「创建对象」提交{id}
GET/ontology/objects/:id选中对象 loadDetail{object_type, properties, links, actions}
GET/ontology/objects/:id/versions选中对象 loadVersions版本数组(含 status/version/base_version/created_by/created_at 等)
POST/ontology/objects/:id/drafts「创建草稿」;属性四连调用第 1 步{version_id}
PUT/ontology/drafts/:vid完整新定义(UpdateDraftRequest)属性四连调用第 2 步{version_id}
POST/ontology/drafts/:vid/review「提交评审」;四连调用第 3 步{version_id, status: "review"}
POST/ontology/drafts/:vid/merge「合入」;四连调用第 4 步{version_id, impact}
POST/ontology/objects/:id/impact合入前弹窗ImpactReport(object_type_id/object_type_name/impacts)
POST/ontology/objects/:id/rollback{target_version}「回滚」{target_version, impact}
POST/ontology/links{object_type_id, name, target_object_type_id, cardinality, direction}「保存」链接{object_type_id, version}
DELETE/ontology/links/:idquery object_type_id「删除」链接{id, version}
POST/ontology/actions{object_type_id, name, edit_type, description, param_schema, validation_rules, write_back_config, idempotency_key_field, requires_approval}「新增动作」弹窗保存{object_type_id, version}
PUT/ontology/actions/:idquery object_type_id;body 同 POST(不含 object_type_id)「编辑」动作(可补写回配置){id, version}
DELETE/ontology/actions/:idquery object_type_id「删除」动作(硬删,删除后名字可复用){id, version}
GET/ontology/interfaces页面加载(onMounted fetchInterfaces);创建表单「实现接口」多选选项源[OntologyInterface](含 id/name/display_name/description),见 models.go:337-345server.go:1240
GET/ontology/shared-properties页面加载(onMounted fetchSharedProperties);创建表单与属性 Tab「共享属性」下拉选项源[OntologySharedProperty](含 id/name/display_name/data_type/constraints),见 models.go:358-368server.go:1248
GET/ontology/value-types本页不直接调用(前端类型下拉来自 constants/valueTypes.js,与该端点目录一一对应)13 类 ValueTypeInfo 数组

5.3 响应结构(JSON 示例)

统一信封:成功 {"code": 0, "data": ...};失败 {"code": "<错误码>", "error": "<详情>"},HTTP 状态取错误码映射(见 5.5)。

GET /ontology/objects 响应示例

{
  "code": 0,
  "data": [
    {
      "object_type": {
        "id": 1,
        "name": "order",
        "rid": "object-type:order",
        "display_name": "订单",
        "description": "",
        "category": "core",
        "data_source_id": 1,
        "base_table": "orders",
        "pk_column": "id",
        "status": "merged",
        "version": 3,
        "created_by": "admin",
        "created_at": "2026-08-30T10:00:00Z",
        "updated_at": "2026-08-30T11:00:00Z"
      },
      "property_count": 5,
      "link_count": 2,
      "action_count": 3
    }
  ]
}

GET /ontology/objects/:id 响应示例(详情面板数据源)

{
  "code": 0,
  "data": {
    "object_type": { "id": 1, "name": "order", "display_name": "订单", "status": "merged", "version": 3, "data_source_id": 1, "base_table": "orders", "pk_column": "id" },
    "properties": [
      { "id": 10, "name": "order_id", "display_name": "订单号", "data_type": "integer", "mapped_column": "order_id", "is_pii": false, "is_primary_key": true, "ordinal": 1 },
      { "id": 11, "name": "amount", "display_name": "金额", "data_type": "currency", "mapped_column": "amount", "is_pii": false, "is_primary_key": false, "ordinal": 2 }
    ],
    "links": [
      { "id": 5, "name": "belongs_to_customer", "source_object_type_id": 1, "target_object_type_id": 2, "cardinality": "N:1", "direction": "directed" }
    ],
    "actions": [
      { "id": 8, "name": "update_status", "description": "更新订单状态", "edit_type": "modify", "param_schema": { "type": "object" } }
    ]
  }
}

POST /ontology/objects/:id/drafts 响应示例

{ "code": 0, "data": { "version_id": 42 } }

POST /ontology/drafts/:vid/merge 响应示例(含影响分析)

{
  "code": 0,
  "data": {
    "version_id": 42,
    "impact": {
      "object_type_id": 1,
      "object_type_name": "order",
      "impacts": [
        { "type": "link", "id": "5", "name": "belongs_to_customer", "detail": "link \"belongs_to_customer\" (1 → 2)target 引用" },
        { "type": "metric", "id": "3", "name": "gmv", "detail": "列 dimensions 内容引用对象 \"order\"" }
      ]
    }
  }
}

POST /ontology/objects/:id/rollback 响应示例

{
  "code": 0,
  "data": { "target_version": 2, "impact": { "object_type_id": 1, "object_type_name": "order", "impacts": [] } }
}

5.4 关联模块表

后端包/文件职责
foundry/ontology/service_impl.go业务服务实现:CreateObjectType / GetObjectType / ListObjectTypes / UpdateObjectType / DeleteObjectType / AddLink / DeleteLink / AddAction / DeleteAction
foundry/ontology/version.go版本状态机:CreateDraft / UpdateDraft / SubmitReview / Approve / Reject / Merge(含冲突检测与审批门禁)/ Rollback / ListVersions
foundry/ontology/impact.go影响分析 AnalyzeImpact(链接/动作/管道/血缘/指标/编辑引用扫描),Merge/Rollback/DeleteObjectType 复用
foundry/ontology/models.go数据模型:OntologyObjectType / OntologyProperty / OntologyLink / OntologyAction / OntologyVersion / ChangeDiff / ObjectSnapshot
foundry/ontology/valuetype.goValueType 13 类冻结类型系统 + GET /ontology/value-types 目录
foundry/ontology/repository.go仓储层:GetFullDefinition / CreateDraftVersion / MergeSnapshotToMain / RollbackToVersion / ListVersions
foundry/server/ontology_handlers.goHTTP handler:对象 CRUD、版本状态机、YAML 导入导出、影响分析、链接/动作子 CRUD、Action 执行
foundry/server/server.go路由注册(protected 分组),见 5.2 端点表
platform/authJWT 认证(authMiddleware,401 语义)
platform/ierr统一错误码与 HTTP 状态映射

5.5 关键机制

(1)版本状态机 draft → review → merged(核心机制)

对象类型结构不允许直接修改线上定义,一切结构变更必须先进入版本状态机:

非法状态转移统一返回错误码 INVALID_VERSION_STATE(HTTP 409),例如 merged 再 merge、draft 未 review 直接 merge、rollback 目标非 merged 等。

(2)影响分析(impact.go)

AnalyzeImpact 扫描对象被引用的位置并返回分组清单 ImpactItem{type, id, name, detail},type 取值 link|action|pipeline|lineage|metric|report|edit

(3)API 错误响应约定

成功 {code: 0, data};失败 {code, error},HTTP 状态由 ierr 映射。本页常见错误码:NOT_FOUND(404)、VALIDATION_ERROR(422)、DUPLICATE_ENTRY(409)、INVALID_VERSION_STATE(409)、APPROVAL_REQUIRED(409)、APPROVAL_DENIED(409)、DATA_SOURCE_NOT_FOUND(404)。

(4)ValueType 13 类冻结目录

属性类型下拉与后端 GET /ontology/value-types 一一对应:text/number/integer/decimal/currency/percentage/date/datetime/bool/enum/json/array<text>/array<number>。前端常量 web/src/constants/valueTypes.js 冻结取值与顺序(B7-1,禁增删改序),类型 label 带括号值(如「文本(text)」。

6. 核心流程详解

6.1 主流程一:创建对象类型

  1. 点击页头「创建对象」,展开创建表单。
  2. 填写基础字段:名称(api_name,必填)、显示名称、数据源 ID(必填,默认 1)、基础表、主键列、多列主键 pk_columns(复合主键时填,逗号分隔)、实现接口 implements_interfaces(多选,可选)、分类、描述;若对象需补充表,在「附加数据源 supplementary_sources」子块点「+ 附加行」逐行填数据源 ID / 补充表名 / 关联条件(设计约定 ≤3,留空不提交)。
  3. 在「属性」子块填属性行(默认 1 行,可点「+ 属性行」追加);属性行第一行含属性名/显示名/数据类型(13 类 ValueType 下拉)/映射列/PII/主键,第二行可填同义词与属性口径说明。空属性名行会在提交时被过滤。
  4. 在「链接」子块点「+ 链接行」添加关系行:链接名、目标对象(从已有对象下拉选择,显示 name(#id))、基数(1:1/1:N/N:M)、方向(directed/bidirectional/undirected)。
  5. 在「动作」子块点「+ 动作行」添加动作行:动作名、编辑类型(modify/create/delete/link)、param_schema JSON,还可填幂等键字段、勾选需审批,并在第二行填 validation_rules / write_back_config JSON。所有 JSON 字段必须是合法 JSON(空可留白),否则提交被前端拦截;复杂写回配置可在对象创建后到详情「动作」Tab 点「编辑」补齐。
  6. 点「创建对象」提交(按钮变「提交中...」禁用)。前端组装完整 payload 调 POST /ontology/objects
  7. 成功提示「对象创建成功 id=N」,重置表单收起,刷新列表;新对象出现在列表(初始 status=merged,version=1)。失败提示「创建失败:<错误详情>」(如数据源不存在 DATA_SOURCE_NOT_FOUND、name 重复 DUPLICATE_ENTRY、字段校验失败 VALIDATION_ERROR)。

6.2 主流程二:选中对象并查看/编辑定义

  1. 点击列表行选中对象 → selectObjectselectedId、清空回滚选择,并行加载详情(GET /ontology/objects/:id)与版本历史(GET /ontology/objects/:id/versions)。
  2. 详情面板出现:标题行显示显示名/状态徽标/v版本号与 meta(name/数据源/表/主键)。
  3. 默认停留在「属性」Tab:表格展示属性名(下含口径小字)/显示名/类型/映射列/同义词/PII/主键;可点「新增属性」展开内联表单(可填同义词、属性口径说明),或点行内「编辑」「删除」。
  4. 切「关系」Tab 查看/新增/删除链接;切「动作」Tab 查看/新增/删除动作。

6.3 主流程三:版本状态机四连调用(属性变更快速合入)

属性 Tab 的「保存/删除」按钮是页面最典型的状态机操作,代码 commitPropertyChange(nextProperties) 按顺序发出 4 个请求:

  1. 建草稿 POST /ontology/objects/{id}/drafts → 得 version_id(版本记录 id)。
  2. 更新草稿 PUT /ontology/drafts/{version_id},请求体为当前对象完整新定义(对象主字段 + 变更后的属性列表 + 原链接 + 原动作)。服务端校验合法后覆盖草稿快照并计算 change_diff。
  3. 提交评审 POST /ontology/drafts/{version_id}/review → draft 变 review。
  4. 合入 POST /ontology/drafts/{version_id}/merge → 过审批门禁与冲突检测后重建主表,生成新 merged 版本。

成功提示「属性保存成功(已生成新 merged 版本)」或「属性"xx"已删除」,随后 loadDetail + loadVersions 刷新。若其中任一步失败(如当前对象已存在进行中的 draft、校验失败、审批门禁拒绝、真冲突),整条链中断,弹「属性保存失败:<详情>」。

版本状态机语义表

状态含义可达操作
draft草稿(版本号 = 最新 merged + 1)UpdateDraft(仅此状态可更新)、SubmitReview(转 review)
review评审中(可审批/驳回)Approve(写 approve 记录)、Reject(写 reject 记录并置回 draft)、Merge
merged已合入(主表已按此快照重建)作为后续 draft 的 base;作为 Rollback 目标;不可再 review/merge
deprecated对象类型软删除状态(对象级,非版本级)

6.4 主流程四:合入与影响分析

「合入」按钮是一个两段式操作

  1. 先取 latestByStatus('review') 找最新 review 版本;没有则提示「没有可合入的 review 版本(请先提交评审)」。
  2. 有则先调 POST /ontology/objects/{id}/impact,弹出「合并前影响分析」模态窗(JSON 原文),让评审者确认下游影响。
  3. 再调 POST /ontology/drafts/{review.id}/merge;成功后提示「版本 vX 已合入」,并弹出「合入结果(影响分析)」展示 merge 返回的 impact(合入后的最新影响扫描)。
  4. 刷新详情与版本列表,状态徽标与版本号更新。

6.5 主流程五:回滚

  1. 从「回滚到版本」下拉选择目标版本(仅列 merged 版本,显示 v{{version}})。
  2. 点「回滚」(未选版本时按钮禁用)。触发 confirm('确定回滚到 vX 吗?将重建主表并生成新版本。')
  3. 确认后调 POST /ontology/objects/{id}/rollback,body {target_version: X}
  4. 成功提示「回滚成功」并弹出「回滚结果(影响分析)」;刷新详情与版本列表。回滚会在版本历史上新增一个 merged 版本(版本号递增),而不是删除历史。

6.6 分支流程:审批门禁(requires_approval 动作)

当对象快照中存在 requires_approval=true 的动作时,SubmitReview 会生成 min_approvals=1self_approval=false 的审批策略。此后「合入」前必须有人对 review 版本执行 Approve(后端路由 POST /ontology/objects/:id/versions/:vid/approve),否则 merge 返回 APPROVAL_REQUIRED。本页当前未内置审批操作入口(审批动作属于版本历史等其它页/接口),因此这类对象在本页「提交评审 → 合入」的链路会被审批门禁拦截,提示合入失败,需通过其它途径完成审批后再合入。这是本页的一个边界(见第 9 章)。

7. 权限与安全

维度说明
认证全部接口走 aip_token Bearer;路由在 protected 分组(JWT authMiddleware)。401 时 client.js 拦截器清除 token 并跳 /login
数据级安全对象定义本身为元数据(无行/列数据),本体工作台不涉及 RLS/CLS 数据行过滤;但属性 is_pii 标记会在下游语义查询/数据打标(markings)中参与列级安全(marking 为 ApplyCLS 之外的第二道列级闸门)
写操作防护页面内所有写操作均有二次确认或前端校验:删除属性/链接/动作用 confirm;回滚用 confirm;动作 param_schema 前端先 JSON.parse 校验;属性保存前校验属性名非空;链接保存前校验名与目标对象非空
审批门禁受保护资源(含 requires_approval 动作)合入前必须过审批门禁(approve 数 ≥ min_approvals、无自批),防止单人无审查直接改线上结构
结构变更审计所有结构变更都以版本记录(ontology_versions)留痕:created_by/created_at/base_version/change_diff;审批记录(ontology_approvals)独立留痕
唯一性约束name 稳定标识唯一索引;草稿改名/回滚 name 重建都做重名预检,冲突返回 DUPLICATE_ENTRY(HTTP 409)

8. 常见问题与排错

8.1 「合入前置版本状态依赖 latestByStatus」——提交评审/合入提示没有可操作的版本

现象:点了「提交评审」却提示「没有可评审的 draft 版本(请先创建草稿)」;或点了「合入」却提示「没有可合入的 review 版本(请先提交评审)」。

原因:前端用 latestByStatus(status)versions 数组中第一个 status === 'draft'(或 'review')的版本。若当前对象不存在对应状态的版本,或版本历史尚未刷新(比如刚创建草稿后版本列表是旧的),就会命中该分支。另外若草稿曾被驳回(reject 置回 draft),状态为 draft 也能重新走评审。

排查步骤

  1. 确认版本列表已刷新:选中对象时会调用 GET /ontology/objects/:id/versions,可打开浏览器 Network 检查该请求最近一次是否成功且包含目标状态版本。
  2. 确认状态:draft 版本的 status 字段必须是 draft 才能评审;review 版本必须是 review 才能合入;merged 版本两者都不能再操作。
  3. 若刚创建草稿,稍等 loadVersions 完成再点「提交评审」;或先重新选中对象行强制刷新详情与版本。

8.2 属性保存报「属性保存失败」且提示 INVALID_VERSION_STATE

现象:属性 Tab 新增/删除属性点「保存」后报错,错误详情含 INVALID_VERSION_STATE 或"only draft can be updated"。

原因commitPropertyChange 四连调用的第一步是无条件 POST /ontology/objects/{id}/drafts 建草稿,但若对象当前已存在进行中的 draft 版本,服务端 CreateDraft 不会重复建草稿(或 UpdateDraft 因目标版本不是 draft 而拒绝),状态机不满足转移条件。属性快速合入要求当前对象处于"无进行中草稿"的干净状态。

排查步骤

  1. 查看版本列表确认是否存在 status=draft 的进行中版本(页面上详情面板没有直接的版本列表,可切到「版本历史」页 /foundry/versions 查看)。
  2. 若有进行中的 draft:先把它完成(提交评审并合入),或先回滚/处理掉,再回来做属性保存。
  3. 若确认无 draft 仍失败,检查响应 error 详情是否为其它错误(校验失败、审批门禁等)。

8.3 「合入」弹影响分析后被 APPROVAL_REQUIRED 拒绝

现象:点「合入」先弹出「合并前影响分析」,紧接着合入请求返回失败,提示 APPROVAL_REQUIRED:merge requires 1 approval(s), got 0。

原因:对象快照含 requires_approval=true 的动作,SubmitReview 时生成 min_approvals=1self_approval=false 审批策略,而本页没有审批入口,approve 数不足导致合入被门禁拦截(这是设计行为)。

排查步骤

  1. 用任意 API 客户端调用 POST /ontology/objects/:id/versions/:vid/approve(vid 为 review 版本记录 id)完成一次审批(非版本创建人身份)。
  2. 或先在「动作」Tab 把 requires_approval 动作调整为不需要审批的配置后重新走一遍草稿链路。
  3. 若审批人为版本创建人且策略禁自批,会被 APPROVAL_DENIED 拒绝,需换一个用户审批。

8.4 创建对象报「数据源 ID 不存在」或 name 重复

现象:「创建对象」提交失败,提示 DATA_SOURCE_NOT_FOUNDDUPLICATE_ENTRY

原因data_source_id 必须指向已存在的数据源(Foundry 数据源管理页配置,如演示数据源 sales_data_warehouse);name(api_name)是全局唯一稳定标识,与已有对象重名即冲突。

排查步骤

  1. 到「数据源」页确认数据源存在且 ID 正确(默认值 1 不一定有效)。
  2. 换一个 name 或用「YAML 导入导出」页检查当前已有哪些对象名。
  3. 若需改名,走「创建草稿 → 更新草稿(改名)→ 评审 → 合入」,注意草稿改名同样受唯一索引约束。

8.5 页面接口报 401 自动跳登录页

现象:操作任意按钮后浏览器跳转到 /login。

原因aip_token 过期/被清,后端返回 401,client.js 响应拦截器清除 token 并重定向。

排查步骤

  1. 重新登录获取新 token。
  2. 若频繁 401,检查系统时间(JWT 过期判定依赖时钟)、SECRET_KEY 是否稳定(SECRET_KEY 过弱/变化会导致 Token 立即过期)。
  3. 检查是否误用其它产品前缀(如 /aip-api 打 18081),路径不匹配时可能 404 而非 401。

8.6 列表加载失败提示「加载对象列表失败」

现象:页面顶部 alert 红条显示「加载对象列表失败:<详情>」。

原因GET /ontology/objects 请求失败(后端未启动、代理未分流、网络超时 30s)。

排查步骤

  1. 确认 Foundry 后端已启动且端口 18081 未被占用。
  2. 确认 Vite 代理将 /api 分流到 18081。
  3. 打开 Network 看具体状态码:404 多为代理分流问题;超时多为后端未响应;500 看后端日志。

9. 已知缺陷与边界

类别说明
无审批 UI页面没有 Approve/Reject 入口;含 requires_approval 动作的对象在本页无法完成完整审批闭环(需走接口或其它页)
版本列表不内嵌详情面板不直接展示版本历史表格(版本信息仅用于回滚下拉与状态徽标),完整版本回溯需切「版本历史」页 /foundry/versions
链接无编辑关系 Tab 仅提供「删除」(与新增),行内没有编辑入口(后端无链接更新端点,需走 YAML 或 API 层);动作 Tab 已支持编辑
对象级高级字段(已于 2026-09-13 补齐)创建表单已暴露多列主键 pk_columns(逗号分隔复合主键)、实现接口 implements_interfaces(多选,选项来自 GET /ontology/interfaces)、附加数据源 supplementary_sources(附加行:数据源 ID / 补充表名 / 关联条件,设计约定 ≤3),属性行与属性 Tab 已暴露共享属性引用 shared_property_id(选项来自 GET /ontology/shared-properties);详情 meta 行同步展示 pk_columns/implements_interfaces/附加数据源个数。边界supplementary_sources 后端(service_impl.go:205/models.go:101)为 JSON 透传存储,Go 侧无结构体形状、无 ≤3 与字段校验,前端表单按设计约定形状(design_foundry.md:203)组装,非法形状不会被后端拦截;precision 后端亦不做强校验
回滚下拉仅列 merged「回滚到版本」只列出 merged 版本;draft/review 版本不可作为回滚目标(符合后端语义)
13 类 ValueType 联动约束(已于 2026-09-13 补齐,enum 更早)属性表单已按 value_type 联动录入约束:currency/percentage 显示并必填单位 unit(对齐后端 validatePropertyTypeConstraints,缺失 422)、decimal 显示小数位 precisionenum 显示枚举值(更早批次已补);三者在提交前组装进 constraints JSON,类型切换时清除无关键。边界precision 后端不做强校验(仅按约定录入);其余 ValueType 无额外约束字段
冲突自动合并语义非冲突自动合并在 (kind, api_name) 维度合并;同名资源双方都改时会按真冲突拦截,页面无冲突可视化提示
前端分页(非服务端分页)列表接口 GET /ontology/objects 无服务端分页参数,仍一次全量拉取;本页已加前端分页 + 关键字过滤(默认每页 20),仅降低渲染开销,不减少网络传输量与请求数据量。对象量极大时仍需后端补分页端点才能根治

注:动作「新增/编辑」能力已于 2026-09-07 补齐(动作 Tab 弹窗支持 param_schema/validation_rules/write_back_config/idempotency_key_field/requires_approval,编辑走 PUT /ontology/actions/:id;创建对象动作行同步补齐)。动作删除为硬删、删除后名字可复用,补配置请在动作 Tab 点「编辑」——整库 YAML 导入对已存在同名对象按 skipped 跳过,属防误覆盖保护。

注:属性保存遇进行中 draft 时的冲突已于 2026-09-06 修复(存在 draft 则复用并覆盖更新、存在 review 则友好提示先合入/回滚,不再无条件新建草稿)。

注:影响分析弹窗只读问题已于 2026-09-06 修复(合入前先弹影响分析,需在弹窗底部点「确认」后才真正执行合入)。

注:deprecated 对象仍在列表展示的问题已于 2026-09-06 修复(对象列表过滤 status=deprecated,不再展示可点但无法正常操作的对象)。

注:对象类型列表的分页/搜索缺口已于 2026-09-13 补齐(前端分页 + 关键字过滤 + 每页条数/翻页/计数,默认每页 20)。边界:列表接口无服务端分页参数,仍为一次全量拉取,前端分页只降低渲染开销、不减少网络传输量(详见 4.4 与第 9 章)。

注:对象级高级字段与 ValueType 联动约束缺口已于 2026-09-13 补齐——创建表单新增「多列主键 pk_columns」「实现接口 implements_interfaces」(选项来自 GET /ontology/interfaces)、「附加数据源 supplementary_sources」(附加行:数据源 ID / 补充表名 / 关联条件);创建属性行与属性 Tab 新增「共享属性引用 shared_property_id」(选项来自 GET /ontology/shared-properties)与按类型联动的「单位 unit」「小数位 precision」;详情 meta 行展示 pk_columns/implements_interfaces/附加数据源个数,属性表类型列展示约束摘要。边界supplementary_sources 后端请求体已支持(service_impl.go:205)但为 JSON 透传存储,Go 侧不校验形状与 ≤3(形状取自设计约定 design_foundry.md:203);precision 后端未做强校验。

后端文件

项目文档

相邻页面链接