Skip to main content
Twenty 中的每个对象都带有你无需自行声明的系统元数据,例如一组字段以及带有列的主列表视图。 当对象被预配置时,服务器会创建所有这些内容,并且随着 Twenty 的发展,这个集合也会随之增长。 由于你不会声明它,因此也就没有可供你导入的 universalIdentifier 常量。 相反,服务器会以确定性方式派生每个标识符,而 twenty-sdk 暴露了相同的派生逻辑,这样你的 manifest 就能解析出服务器实际使用的精确值。

系统字段

存在于每个对象上的标量字段,你不会使用 defineField() 来声明其中任何一个: id, createdAt, updatedAt, deletedAt, createdBy, updatedBy, position, searchVector 那么,如何在视图中将 createdAt 作为一列来引用呢?

问题

从 Twenty 2.19 起,系统字段的通用标识符由服务器根据三个输入确定性派生:应用通用标识符、对象通用标识符以及字段名称。 自行构造一个 id 并将其硬编码是行不通的:它在服务器上不会匹配任何内容,同步时会拒绝这个悬空引用:

解决方案

getFieldUniversalIdentifiertwenty-sdk 2.21 版本开始可用。
使用 getFieldUniversalIdentifier 来解析与服务器使用的值完全相同的字段标识符。 它接收这三个输入,并返回字段的通用标识符:
  • applicationUniversalIdentifier 是你的应用标识符,也就是你传递给 defineApplication() 的那个。
  • objectUniversalIdentifier 是该字段所属对象的标识符。
  • name 是系统字段名称,为上面列出的值之一。

示例:视图中的 createdAt 列

典型场景是:为你某个自定义对象的视图添加一列 createdAt。 解析字段 id,并像引用其他 fieldMetadataUniversalIdentifier 一样引用它:
src/views/example-view.ts
同一个解析得到的 id 可在任何需要 fieldMetadataUniversalIdentifier 的地方使用:视图字段、筛选器、排序、分组以及页面布局挂件。
解析 id,而不是将其硬编码。 由于服务器是根据应用 id、对象 id 和字段名来派生该值的,调用 getFieldUniversalIdentifier 能在这些输入发生变化时仍保持引用正确,并在派生逻辑演进时避免偏差。

系统关系字段

getSystemRelationFieldUniversalIdentifier 可在 twenty-sdk 2.23 及更高版本中使用,并且需要 Twenty 服务器版本为 2.23 或更高。
除了上面的标量系统字段之外,服务器还会在每个对象上预置四个系统关系字段timelineActivitiesattachmentsnoteTargetstaskTargets,它们各自指向相应的标准关系对象。 这些字段不会通过 getFieldUniversalIdentifier 解析:其标识符不依赖名称,而是由承载该字段的对象和该字段指向的对象推导而来。 通过这种方式,重命名对象永远不会改变其关系字段的标识符。 使用 getSystemRelationFieldUniversalIdentifier 来解析它们:
  • objectUniversalIdentifier承载该字段的对象。
  • relationTargetObjectUniversalIdentifier 是该字段指向的对象。
方向由参数的顺序编码。 要解析反向端(例如 attachment.targetRocket,即服务器在标准关系对象上创建的 morph 字段),交换这两个参数:
与标量系统字段一样,解析得到的 id 可在任何需要 fieldMetadataUniversalIdentifier 的地方使用。

系统视图

getSystemViewUniversalIdentifiergetSystemViewFieldUniversalIdentifier 可在 twenty-sdk 2.26 及更高版本中使用,并且需要 Twenty 服务器版本为 2.26 或更高。
服务器还会在每个对象上预配置一个系统视图:主列表视图(All {objectLabelPlural},以 ViewKey.INDEX 作为键),其中每个可显示字段对应一列。 与系统关联字段类似,它们的标识符是以与名称无关的方式派生的,因此重命名对象或字段都不会改变这些标识符。 使用 getSystemViewUniversalIdentifier 来解析该视图:
  • objectMetadataApplicationUniversalIdentifier 是拥有该对象的应用程序,也是视图命名空间所基于的应用。
  • objectUniversalIdentifier 是该视图所列出的对象。
  • viewKey 是系统视图键,目前为 ViewKey.INDEX
解析得到的 id 可用于任何需要 viewUniversalIdentifier 的地方,例如侧边栏中的 NavigationMenuItemType.VIEW 条目。 如果只是要打开某个对象的主列表,优先使用带有 targetObjectUniversalIdentifierNavigationMenuItemType.OBJECT:它不需要派生。 getSystemViewFieldUniversalIdentifier 会从视图以及其显示的字段中解析系统视图上的单个
注意第一个参数:列是由其显示的字段所属的应用程序进行命名空间划分的,而不是由拥有该视图的应用程序进行划分。 你的应用向标准对象添加的字段,会在 Twenty 拥有的视图上,以你的应用为命名空间来派生其列。
系统视图及其列是由服务器所有的:解析它们的标识符是为了引用它们,而不是为了声明它们。 defineView() 上的 key 已被弃用且会被忽略,因此 manifest 视图永远无法占用 INDEX 键,并且服务器已经为你添加的每个字段预配置了一列,所以在系统视图上为同一个字段声明你自己的 defineViewField() 会与其发生冲突。

标准 Twenty 对象

对于标准 Twenty 对象(Person、Company、Opportunity 等),你不需要进行任何派生:字段和视图的标识符都是预先计算好的常量,你可以直接导入。
当对象是由你的应用使用 defineObject() 定义、且不存在此类常量时,再使用上面的辅助方法。
name 是一个默认字段,而不是系统字段。 它保留自己的硬编码 通用标识符,而不是通过 getFieldUniversalIdentifier 解析。 在你定义的对象上,请使用你在 defineObject() 中赋予它的标识符来引用 name 字段。