name: content-type-modeling description: 当设计内容类型层次结构、定义可重用的内容部分或为 headless CMS 结构化字段组合时使用。涵盖了内容类型 -> 内容部分 -> 内容字段的层次模式、内容类型继承、组合与继承的权衡以及跨通道最大可重用性的模式设计。 allowed-tools: Read, Glob, Grep, Task, Skill, AskUserQuestion
内容类型建模
交互式建模配置
使用 AskUserQuestion 来配置内容类型建模会话:
# 问题 1: 建模范围 (MCP: CMS 内容架构模式)
question: "您需要什么内容类型建模?"
header: "范围"
options:
- label: "单一类型(推荐)"
description: "设计一个带有部分和字段的内容类型"
- label: "类型家族"
description: "共享公共部分的相关内容类型"
- label: "完整分类法"
description: "带有关系的完整内容模型"
- label: "迁移"
description: "从传统内容迁移到结构化内容"
# 问题 2: 可重用性策略 (MCP: Orchard Core 内容模式)
question: "内容部分应如何结构化?"
header: "重用"
options:
- label: "组合(推荐)"
description: "从可重用部分构建类型 - 最大灵活性"
- label: "继承"
description: "带有专门扩展的基础类型"
- label: "混合"
description: "组合和继承的混合"
- label: "扁平"
description: "每个类型上的独立字段 - 没有共享部分"
使用这些响应来确定建模范围和组合策略。
设计 headless CMS 架构的内容类型层次结构、可重用部分和字段组合的指导。
何时使用此技能
- 为新 CMS 设计内容类型模式
- 定义跨多个类型的可重用内容部分
- 结构化自定义字段组合
- 规划内容类型继承策略
- 从传统内容迁移到结构化内容
- 创建多通道内容架构
三级层次结构
Headless CMS 平台通常使用三级内容层次结构,灵感来自 Orchard Core 和类似平台:
内容类型(例如,“博客文章”、“产品”、“事件”)
├── 内容部分(可重用的字段组)
│ ├── TitlePart(标题,显示标题)
│ ├── AutoroutePart(slug,URL 模式)
│ ├── PublishLaterPart(计划发布)
│ └── [自定义部分]
└── 内容字段(个别数据元素)
├── TextField(单行,多行)
├── HtmlField(富文本)
├── MediaField(图像,文档)
├── ContentPickerField(引用)
└── [自定义字段]
内容类型
内容类型是内容项的蓝图。它们定义了可用的部分和字段。
content_type:
name: BlogPost
display_name: Blog Post
description: 带有作者和类别的博客文章
stereotype: Content # Content, Widget, MenuItem
creatable: true
listable: true
draftable: true
versionable: true
securable: true
关键决策:
| 决策 | 选项 | 推荐 | | 命名 | 单数 vs 复数 | 单数(BlogPost,不是 BlogPosts) | | 刻板印象 | Content, Widget, MenuItem | Content 用于独立,Widget 用于可嵌入 | | 可起草 | true/false | true 用于编辑内容 | | 可版本化 | true/false | true 用于审计要求 |
内容部分
内容部分是可重用的字段组,可以附加到多个内容类型。它们促进 DRY 原则。
content_part:
name: SeoMetaPart
description: 搜索引擎的 SEO 元数据
fields:
- name: MetaTitle
type: TextField
settings:
max_length: 60
hint: "搜索结果显示的标题"
- name: MetaDescription
type: TextField
settings:
max_length: 160
editor: TextArea
- name: MetaKeywords
type: TextField
settings:
editor: TextArea
hint: "逗号分隔的关键词"
- name: NoIndex
type: BooleanField
settings:
default: false
常见可重用部分:
| 部分 | 目的 | 附加到 | | TitlePart | 标题和显示标题 | 所有内容类型 | | AutoroutePart | URL slug 生成 | 页面,文章 | | PublishLaterPart | 计划发布 | 编辑内容 | | LocalizationPart | 多语言支持 | 可翻译内容 | | SeoMetaPart | 搜索引擎元数据 | 公共页面 | | CommonPart | 所有者,创建/修改日期 | 所有内容类型 | | ContainablePart | 父容器引用 | 层次内容 |
内容字段
内容字段是附加到部分或直接附加到内容类型的个别数据元素。
标准字段类型:
| 字段类型 | 目的 | 示例使用 | | TextField | 单行/多行文本 | 标题,描述 | | HtmlField | 带格式的富文本 | 主体内容 | | NumericField | 数字(整数,小数) | 价格,数量 | | BooleanField | 真/假切换 | 特色,已发布 | | DateTimeField | 日期和/或时间 | 事件日期,截止日期 | | MediaField | 图像,文档,视频 | 英雄图像,附件 | | ContentPickerField | 引用其他内容 | 作者,相关文章 | | TaxonomyField | 类别/标签选择 | 类别,标签 | | LinkField | 带有可选文本的 URL | 外部链接 | | UserPickerField | 引用用户 | 作者,分配者 |
组合与继承
组合模式(推荐)
通过组合部分来构建内容类型。这是灵活性的首选方法。
# 博客文章 = TitlePart + AutoroutePart + BodyPart + SeoMetaPart + 自定义字段
content_type:
name: BlogPost
parts:
- TitlePart
- AutoroutePart
- PublishLaterPart
- SeoMetaPart
fields:
- name: FeaturedImage
type: MediaField
- name: Author
type: ContentPickerField
settings:
content_types: [Author]
- name: Categories
type: TaxonomyField
settings:
taxonomy: BlogCategories
好处:
- 部分可跨类型重用
- 对部分的更改影响所有附加类型
- 清晰的关注点分离
- 更容易添加/删除功能
继承模式
谨慎使用于真正的“是-a”关系。
# 基础类型
content_type:
name: Article
abstract: true # 不能直接创建实例
parts:
- TitlePart
- AutoroutePart
- BodyPart
# 派生类型
content_type:
name: NewsArticle
extends: Article
fields:
- name: BreakingNews
type: BooleanField
content_type:
name: OpinionPiece
extends: Article
fields:
- name: OpinionAuthor
type: ContentPickerField
何时使用继承:
- 清晰的“是-a”关系
- 跨子类型共享行为
- 需要多态查询
- 有限层次深度(最多2-3层)
字段设计最佳实践
命名约定
做:
- PascalCase 用于类型/部分/字段名称:BlogPost, FeaturedImage
- 描述性名称指示目的:PublishDate(不是 Date1)
- 一致的后缀:*Date, *Image, *List
不做:
- 缩写:PubDt, FeatImg
- 通用名称:Data, Value, Field1
- 不一致的大小写:blogPost, featured_image
字段验证
field:
name: Email
type: TextField
validation:
required: true
pattern: "^[^@]+@[^@]+\\.[^@]+$"
max_length: 255
unique: true # 在内容类型内
settings:
placeholder: "user@example.com"
hint: "输入有效的电子邮件地址"
必需与可选字段
必需字段:
- 内容有意义所必需的
- 用于 URL 或标识
- API 消费者需要
可选字段:
- 增强功能或元数据
- 可能不适用于所有实例
- 编辑器中逐步披露
内容类型类别
系统内容类型
内置类型,支持 CMS 功能:
| 类型 | 目的 | | Menu | 导航结构 | | MenuItem | 个别菜单链接 | | Taxonomy | 类别/标签词汇表 | | TaxonomyTerm | 个别术语 | | MediaAsset | 图像,文档 | | User | 用户资料 |
常见内容类型
跨 CMS 项目经常需要:
# Page - 通用内容页面
content_type:
name: Page
parts: [TitlePart, AutoroutePart, BodyPart, SeoMetaPart]
fields:
- name: FeaturedImage
type: MediaField
optional: true
# Article - 博客文章,新闻文章
content_type:
name: Article
parts: [TitlePart, AutoroutePart, BodyPart, SeoMetaPart, PublishLaterPart]
fields:
- name: Author
type: ContentPickerField
- name: FeaturedImage
type: MediaField
- name: Categories
type: TaxonomyField
- name: Tags
type: TaxonomyField
- name: ReadTime
type: NumericField
computed: true
# Event - 日历事件
content_type:
name: Event
parts: [TitlePart, AutoroutePart, BodyPart]
fields:
- name: StartDate
type: DateTimeField
required: true
- name: EndDate
type: DateTimeField
- name: Location
type: TextField
- name: VirtualLink
type: LinkField
- name: RegistrationUrl
type: LinkField
API 考虑
内容类型到 API 形状
内容类型应清晰地映射到 API 响应:
{
"id": "abc123",
"contentType": "BlogPost",
"displayText": "我的博客文章标题",
"createdUtc": "2025-01-15T10:30:00Z",
"modifiedUtc": "2025-01-15T14:22:00Z",
"publishedUtc": "2025-01-15T14:22:00Z",
"owner": "user123",
"parts": {
"TitlePart": {
"title": "我的博客文章标题"
},
"AutoroutePart": {
"path": "/blog/我的博客文章标题"
}
},
"fields": {
"FeaturedImage": {
"paths": ["/media/hero.jpg"],
"alt": "英雄图像"
},
"Author": {
"contentItemIds": ["author456"]
},
"Categories": {
"termIds": ["cat1", "cat2"]
}
}
}
GraphQL 模式生成
内容类型通常映射到 GraphQL 类型:
type BlogPost implements ContentItem {
contentItemId: ID!
contentType: String!
displayText: String
createdUtc: DateTime
publishedUtc: DateTime
# 部分
titlePart: TitlePart
autoroutePart: AutoroutePart
# 字段
featuredImage: MediaField
author: ContentPickerField
categories: TaxonomyField
}
迁移策略
从传统到结构化
1. 审计现有内容
- 记录当前结构
- 识别重复模式
- 注意关系
2. 设计目标模式
- 将字段分组到部分
- 定义内容类型
- 规划分类法
3. 创建映射
- 旧字段 -> 新字段
- 需要的数据转换
- 新字段的默认值
4. 增量迁移
- 从简单类型开始
- 每批后验证
- 保持旧系统并行运行
内容类型检查清单
在最终确定内容类型之前:
- [ ] 清晰、描述性的名称
- [ ] 适当的部分附加
- [ ] 所有必要的字段定义
- [ ] 验证规则指定
- [ ] 必需与可选明确标记
- [ ] API 形状考虑
- [ ] 本地化要求解决
- [ ] 搜索索引配置
- [ ] 预览/显示模板规划
- [ ] 编辑体验优化
相关技能
dynamic-schema-design- EF Core JSON 列用于自定义字段content-relationships- 内容项之间的引用content-versioning- 草稿/发布和版本历史taxonomy-architecture- 类别和标签headless-api-design- 内容交付 API