内容类型定义
内容类型是 CMS 的核心概念,它定义了内容的结构和行为。本文将介绍如何定义和管理内容类型。
基本定义
1. 创建内容类型
创建一个继承自 ContentBase<T>
的类来定义内容类型:
[Description("文章")]
public class Article : ContentBase<Article>
{
/// <summary>
/// 标题
/// </summary>
[Display(Name = "标题")]
[Required]
public TextFieldType Title { get; set; } = null!;
/// <summary>
/// 内容
/// </summary>
[Display(Name = "内容")]
[MarkdownToolBar(MarkdownToolStyle.Standard)]
public MarkdownFieldType? Content { get; set; }
/// <summary>
/// 发布日期
/// </summary>
[Display(Name = "发布日期")]
public DateTimeFieldType? PublishDate { get; set; }
/// <summary>
/// 是否发布
/// </summary>
[Display(Name = "是否发布")]
public BooleanFieldType IsPublished { get; set; }
/// <summary>
/// 作者
/// </summary>
[Display(Name = "作者")]
public TextFieldType? Author { get; set; }
/// <summary>
/// 标签
/// </summary>
[Display(Name = "标签")]
[ArrayField(10, 5)]
public ArrayFieldType? Tags { get; set; }
public override string Content_Description => "文章内容";
}
2. 字段类型
Biwen.QuickApi.Contents 提供了多种字段类型:
TextFieldType
: 文本字段TextAreaFieldType
: 多行文本字段MarkdownFieldType
: Markdown 编辑器字段NumberFieldType
: 数字字段IntegerFieldType
: 整数字段BooleanFieldType
: 布尔字段DateTimeFieldType
: 日期时间字段TimeFieldType
: 时间字段UrlFieldType
: URL 字段ColorFieldType
: 颜色字段FileFieldType
: 文件字段ImageFieldType
: 图片字段OptionsFieldType
: 单选字段OptionsMultiFieldType
: 多选字段ArrayFieldType
: 数组字段
高级定义
1. 继承关系
内容类型可以继承其他内容类型:
[Description("博客文章")]
public class BlogPost : Article
{
/// <summary>
/// 分类
/// </summary>
[Display(Name = "分类")]
[OptionsField("技术", "生活", "其他")]
public OptionsFieldType? Category { get; set; }
/// <summary>
/// 封面图片
/// </summary>
[Display(Name = "封面图片")]
public ImageFieldType? CoverImage { get; set; }
}
2. 字段属性
使用特性来定义字段的属性:
[Display(Name = "标题")] // 显示名称
[Required] // 必填
[MaxLength(100)] // 最大长度
[Description("文章标题")] // 描述
[MarkdownToolBar(MarkdownToolStyle.Standard)] // Markdown 工具栏样式
[ArrayField(10, 5)] // 数组字段限制
[OptionsField("选项1", "选项2")] // 选项字段
使用方式
1. 内容创建
public class ArticleService
{
private readonly IContentService _contentService;
public async Task<Article> CreateArticleAsync(CreateArticleDto dto)
{
var article = new Article
{
Title = new TextFieldType { Value = dto.Title },
Content = new MarkdownFieldType { Value = dto.Content },
PublishDate = new DateTimeFieldType { Value = DateTime.Now },
Author = new TextFieldType { Value = dto.Author },
Tags = new ArrayFieldType { Values = dto.Tags }
};
await _contentService.CreateAsync(article);
return article;
}
}
2. 内容查询
public class ArticleQueryService
{
private readonly IContentService _contentService;
public async Task<IEnumerable<Article>> GetPublishedArticlesAsync()
{
return await _contentService.Query<Article>()
.Where(x => x.IsPublished.Value)
.OrderByDescending(x => x.PublishDate.Value)
.ToListAsync();
}
}
最佳实践
字段设计
- 使用合适的字段类型
- 添加必要的验证规则
- 提供清晰的字段描述
- 考虑字段的扩展性
类型设计
- 保持类型职责单一
- 合理使用继承
- 考虑性能影响
- 提供合适的默认值
验证规则
- 使用字段类型内置的验证
- 提供清晰的错误信息
- 考虑业务规则
示例
1. 产品内容类型
[Description("产品")]
public class Product : ContentBase<Product>
{
[Display(Name = "产品名称")]
[Required]
public TextFieldType Name { get; set; } = null!;
[Display(Name = "产品描述")]
[MarkdownToolBar(MarkdownToolStyle.Standard)]
public MarkdownFieldType? Description { get; set; }
[Display(Name = "价格")]
[Required]
public NumberFieldType Price { get; set; } = null!;
[Display(Name = "分类")]
[OptionsMultiField("电子产品", "家居用品", "服装")]
public OptionsMultiFieldType? Categories { get; set; }
[Display(Name = "规格")]
[ArrayField(10, 5)]
public ArrayFieldType? Specifications { get; set; }
[Display(Name = "产品图片")]
public ImageFieldType? ProductImage { get; set; }
public override string Content_Description => "产品信息";
}
2. 页面内容类型
[Description("页面")]
public class Page : ContentBase<Page>
{
[Display(Name = "标题")]
[Required]
public TextFieldType Title { get; set; } = null!;
[Display(Name = "URL别名")]
public TextFieldType? Slug { get; set; }
[Display(Name = "内容")]
[MarkdownToolBar(MarkdownToolStyle.Standard)]
public MarkdownFieldType? Content { get; set; }
[Display(Name = "Meta描述")]
public TextAreaFieldType? MetaDescription { get; set; }
[Display(Name = "关键词")]
[ArrayField(10, 5)]
public ArrayFieldType? Keywords { get; set; }
public override string Content_Description => "页面内容";
}