Content
最后更新:2026年7月3日
Content 是用 Content Type(模板)生成的一条实际数据。以服装电商为例,Content Type“商品”规定了商品名、价格、详细说明等条目的构成,而一件“Stainless Tumbler 500ml”就是遵循该模板的一条 Content。
Content 由两部分组成。fields 中存放各字段的实际值,sys 中存放发布、版本、归档等状态。在 CMA 中,Content 是 Space 的子资源,查询与删除路径以 /spaces/{spaceId}/contents 为准,创建与修改路径以 Content Type 子级的 /spaces/{spaceId}/content-types/{contentTypeId}/contents 为准。管理操作在 CMA 中执行,已发布的快照通过 CDA 进行传递。
资源结构
下面是已发布的 Content“Stainless Tumbler 500ml”的单条查询响应。除 sys(系统属性)外,还包含 fields(字段值)和 metadata(标签等附加信息)。
{
"sys": {
"id": "3trmXRM3RqbgSnifyg7PUl8DzDgDzP",
"type": "Content",
"space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
"contentType": { "sys": { "id": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA", "type": "Refer", "targetType": "ContentType" } },
"publish": {
"version": 1,
"at": "2026-06-18T09:51:44.128Z",
"firstAt": "2026-06-18T09:51:44.128Z",
"counter": 1,
"by": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } }
},
"createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"createdAt": "2026-06-18T09:51:14.597Z",
"updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"updatedAt": "2026-06-18T09:51:44.128Z",
"version": 2,
"status": "Published"
},
"fields": {
"price": { "en-US": 18000 },
"productName": { "en-US": "Stainless Tumbler 500ml", "ko-KR": "스테인리스 텀블러 500ml" }
},
"metadata": { "tags": [] }
}主要键:
sys.id:Content 的唯一标识符。会填入单条查询、修改、删除、发布路径中的{contentId}。sys.contentType:指向该 Content 所遵循的 Content Type 的Refer。fields:各字段的值。键是字段的apiName,值是按 Locale 划分的映射。详见下文 字段键就是 apiName。metadata.tags:为该 Content 添加的 Tag 列表。每一项的形态为Refer<Tag>,若没有标签则为空数组[]。
字段键就是 apiName
fields 对象的键是各字段的 apiName。它不是 Content Type 的内部 id,也不是内容工作室中显示的字段名(例如 商品名)。因此创建或读取 Content 时,必须用 Content Type 中定义的 apiName 作为键。
演示用“商品” Content Type 的字段及其 apiName 映射如下。
| 内容工作室名称 | apiName | type | localized | required |
|---|---|---|---|---|
| 商品名 | productName | ShortText | true | true |
| 价格 | price | Long | false | false |
| 详细说明 | description | RichText | true | false |
| 主图 | photo | Refer<Media> | false | false |
| 品牌 | brand | Refer | false | false |
每个字段值都是按 Locale 划分的映射。值的形态取决于 localized。
localized: true字段可以采用{ "<locale>": 值 }的形态持有多个 Locale 值。例如:"productName": { "en-US": "Stainless Tumbler 500ml", "ko-KR": "스테인리스 텀블러 500ml" }。localized: false字段(非本地化字段)只在 Space 默认 Locale 这一个键下填入值,不能填入其他 Locale 键。演示用 Space 的默认 Locale 是en-US,因此价格只持有en-US这一个键,如"price": { "en-US": 18000 }。
关于默认 Locale 是什么、required 字段需要填到哪些 Locale、以及无值时的 fallback 规则,请参见 多语言(概念)。
各类型的值形态
填入 Locale 键内部的值的形态取决于字段的 type。大多数类型直接填入该类型的值(文本类型为字符串,Number、Long 为数字,Boolean 为 true/false)。由于形态是对象或数组而容易混淆的类型如下。
Location:是{ "latitude": <数字>, "longitude": <数字> }对象。latitude取值在 -90 到 90 之间,longitude取值在 -180 到 180 之间,两个键都是必填。除已定义的键外不接受其他键,因此使用lat、lng、lon这类缩写键会被拒绝。Refer:值是指向目标的Refer对象,不能只填 id 字符串,而要直接填入sys对象。指向其他 Content 时targetType为Content,指向 Media 时为Media。Refer形态本身在 系统属性 (sys) 的 Refer 形态 中定义。Array:是装有元素类型值的 JSON 数组。元素为文本时是字符串数组,元素为Refer(Content 或 Media)时是Refer对象的数组,而不是 id 字符串的数组。
下面是填入 fields 内部的值的示例(Space 默认 Locale 为 en-US 的情况)。
{
"location": { "en-US": { "latitude": 37.5662, "longitude": 126.9910 } },
"tags": { "en-US": ["新品", "限量版"] },
"photo": { "en-US": { "sys": { "type": "Refer", "id": "3trmXRM3RqbgSnifyg7PUl8DzDgDzP", "targetType": "Media" } } },
"photos": { "en-US": [ { "sys": { "type": "Refer", "id": "3trmXRM3RqbgSnifyg7PUl8DzDgDzP", "targetType": "Media" } } ] }
}系统属性 (sys)
每个 Content 都将公共系统属性存放在 sys 对象中。space、contentType、createdBy、updatedBy 以 Refer 形态({ "sys": { "id", "type": "Refer", "targetType" } })填入。
| 属性 | 类型 | 说明 |
|---|---|---|
id | string | 资源唯一标识符。 |
type | string | 资源种类。Content 始终为 "Content"。 |
space | Refer<Space> | 该 Content 所属的 Space。 |
contentType | Refer<ContentType> | 该 Content 所遵循的 Content Type。 |
publish | object | 发布状态指针。参见下方各键。 |
archive | object | 归档信息。仅在归档时存在,否则没有该键。参见下方各键。 |
createdBy | Refer<User> | 创建该资源的用户。 |
createdAt | string (date-time) | 创建时间。 |
updatedBy | Refer<User> | 最后修改的用户。 |
updatedAt | string (date-time) | 最后修改时间。 |
version | integer (≥1) | 资源版本。每次创建、修改、发布、取消发布、归档等变更都会加 1。 |
status | string (enum) | 发布状态。为下列 4 种之一。 |
status 为下列 4 种之一。
status | 含义 |
|---|---|
Draft | 正在编写、尚未发布的状态。 |
Changed | 曾经发布过,但之后被修改、尚有未发布变更的状态。 |
Published | 已发布且没有未发布变更的状态。 |
Archived | 已归档的状态。 |
publish 对象是指向发布状态的指针。处于已发布时拥有以下全部键。
| 键 | 类型 | 说明 |
|---|---|---|
version | integer | 发布时的 sys.version。 |
at | string (date-time) | 最后发布时间。 |
firstAt | string (date-time) | 首次发布时间。即使取消发布也会保留。 |
counter | integer | 累计发布次数。 |
by | Refer<User> | 最后发布的用户。 |
取消发布后,publish 中的 version、at、by 会被去除,只保留 firstAt、counter。若从未发布过,则 publish 为 { "counter": 0 }。
archive 对象仅在归档时存在。归档时拥有 version(归档时的 sys.version)、at(归档时间)、by(归档的用户);非归档状态时则没有 archive 键本身。
下方示例中的 sys.version 与所有时间值都是实际调用时刻的值,每次调用都会不同。
发布、版本与并发
Content 的生命周期如下。
- 创建后
status为Draft。Content在创建时不会自动发布。这一点与 Content Type 不同。Content Type 在创建的同时会自动发布,而 Content 必须经过单独的发布调用才会进入传递路径。 - 发布后
status变为Published。 - 发布后再修改,
status会变为Changed,表示存在未发布的变更。 - 取消发布后
status会再次变回Draft。 - 要归档必须先取消发布。处于已发布状态的 Content 无法直接归档。
sys.version 每次变更都会加 1。
修改、部分修改、发布、取消发布、归档、取消归档的请求都必须在 x-weegloo-version 头中携带当前的 sys.version。若该值缺失或与当前版本不一致,将被视为并发修改冲突,请求会被拒绝。创建与删除请求不带此头。发布、取消发布、归档、取消归档等状态转换没有单独的请求体。
API
下面所有端点的基准 URL 均为 https://cma.weegloo.com/v1,并且 Authorization 头需要携带用于认证 CMA 的 Bearer 令牌。修改、部分修改、发布、取消发布、归档、取消归档为实现乐观并发控制,必须同时发送 X-Weegloo-Version 头(当前资源的 sys.version)。
用 fields.* 对 /contents 列表(GET /spaces/{spaceId}/contents)进行过滤或排序时,必须同时以 sys.contentType.sys.id={contentTypeId} 指定 Content Type。contentType={contentTypeId} 这种形式无法替代。/content-types/{contentTypeId}/contents 已在路径中明示了 Content Type,因此无需另行指定。
相关文档
- Content Type:该 Content 的模板(字段定义、apiName)。
- CDA Content:将已发布的 Content 传递给访客(读取)。
- Tag:添加到 metadata.tags 的分类标签。
- 多语言(概念):默认 Locale、必填填充、fallback。
