页面结构设计Skill page-structure-design

页面结构设计技能提供全面指导,用于设计头寸CMS的页面层次结构、模板系统和模块化页面组合。覆盖页面集、模板继承、组件区域和页面树API,帮助构建灵活的网站架构,优化SEO和用户体验。关键词:页面结构设计、头寸CMS、模板系统、页面构建器、站点地图生成、模块化页面组合。

架构设计 0 次安装 0 次浏览 更新于 3/11/2026

name: 页面结构设计 description: 在设计页面层次结构、页面模板、布局区域或站点地图结构时使用。覆盖页面集、模板继承、组件区域和头寸CMS架构的页面树API。 allowed-tools: Read, Glob, Grep, Task, Skill

页面结构设计

为头寸CMS设计页面层次结构、模板和模块化页面组合系统的指导。

何时使用此技能

  • 设计页面树结构
  • 创建带有区域的页面模板
  • 实现页面构建器功能
  • 规划站点地图生成
  • 构建模块化页面组合

页面层次结构模式

基本页面树

public class Page
{
    public Guid Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public string Slug { get; set; } = string.Empty;

    // 层级结构
    public Guid? ParentId { get; set; }
    public Page? Parent { get; set; }
    public List<Page> Children { get; set; } = new();

    // 计算路径
    public string Path { get; set; } = string.Empty; // /about/team/leadership
    public int Depth { get; set; }
    public int Order { get; set; }

    // 模板和内容
    public string Template { get; set; } = string.Empty;
    public PageContent Content { get; set; } = new();
}

页面集(集合)

// 用于分组相关页面的页面集
public class PageSet
{
    public Guid Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Slug { get; set; } = string.Empty;
    public PageSetType Type { get; set; }

    // 配置
    public string ItemTemplate { get; set; } = string.Empty;
    public string ListTemplate { get; set; } = string.Empty;
    public int ItemsPerPage { get; set; } = 10;

    // URL 模式
    public string UrlPattern { get; set; } = string.Empty; // /blog/{slug}
}

public enum PageSetType
{
    Blog,       // 按时间顺序的帖子
    Portfolio,  // 项目展示
    Team,       // 团队成员
    Products,   // 产品目录
    FAQ,        // 问答集合
    Custom      // 用户定义
}

模板系统

模板定义

public class PageTemplate
{
    public string Name { get; set; } = string.Empty;
    public string DisplayName { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;

    // 模板层次结构
    public string? ParentTemplate { get; set; }

    // 可用的内容区域
    public List<TemplateZone> Zones { get; set; } = new();

    // 必填字段
    public List<TemplateField> Fields { get; set; } = new();

    // 适用的页面类型
    public List<string> ApplicablePageTypes { get; set; } = new();
}

public class TemplateZone
{
    public string Name { get; set; } = string.Empty;
    public string DisplayName { get; set; } = string.Empty;
    public ZoneType Type { get; set; }
    public List<string> AllowedWidgets { get; set; } = new();
    public int? MaxWidgets { get; set; }
}

public enum ZoneType
{
    Single,     // 仅一个部件
    Multiple,   // 多个部件堆叠
    Grid        // 网格布局
}

模板继承

基础模板
├── 区域:头部,底部,侧边栏
└── 字段:元标题,元描述

    ├── 首页模板(继承基础)
    │   └── 区域:英雄区域,功能区域,行动召唤区域
    │
    ├── 内容模板(继承基础)
    │   └── 区域:主要内容,相关内容
    │
    └── 着陆页模板(继承基础)
        └── 区域:英雄区域,区域块(多个)

页面构建器组件

部件系统

public abstract class Widget
{
    public Guid Id { get; set; }
    public string Type { get; set; } = string.Empty;
    public int Order { get; set; }
    public Dictionary<string, object?> Settings { get; set; } = new();
}

public class TextWidget : Widget
{
    public string Content { get; set; } = string.Empty;
}

public class ImageWidget : Widget
{
    public Guid MediaItemId { get; set; }
    public string? Alt { get; set; }
    public string? Caption { get; set; }
}

public class CallToActionWidget : Widget
{
    public string Heading { get; set; } = string.Empty;
    public string? Subheading { get; set; }
    public string ButtonText { get; set; } = string.Empty;
    public string ButtonUrl { get; set; } = string.Empty;
    public string? BackgroundImageId { get; set; }
}

public class CardGridWidget : Widget
{
    public List<Card> Cards { get; set; } = new();
    public int Columns { get; set; } = 3;
}

页面内容结构

public class PageContent
{
    // 基于区域的内容存储
    public Dictionary<string, List<Widget>> Zones { get; set; } = new();

    // 页面级字段
    public string? HeroTitle { get; set; }
    public string? HeroSubtitle { get; set; }
    public Guid? HeroImageId { get; set; }

    // SEO
    public string? MetaTitle { get; set; }
    public string? MetaDescription { get; set; }
    public bool NoIndex { get; set; }
}

站点地图生成

站点地图数据模型

public class SitemapEntry
{
    public string Url { get; set; } = string.Empty;
    public DateTime LastModified { get; set; }
    public ChangeFrequency ChangeFrequency { get; set; }
    public decimal Priority { get; set; }
    public List<SitemapAlternate>? Alternates { get; set; }
}

public class SitemapAlternate
{
    public string Hreflang { get; set; } = string.Empty;
    public string Url { get; set; } = string.Empty;
}

public enum ChangeFrequency
{
    Always,   // 总是
    Hourly,   // 每小时
    Daily,    // 每天
    Weekly,   // 每周
    Monthly,  // 每月
    Yearly,   // 每年
    Never     // 从不
}

站点地图生成服务

public class SitemapService
{
    public async Task<List<SitemapEntry>> GenerateSitemapAsync()
    {
        var entries = new List<SitemapEntry>();

        // 添加页面
        var pages = await _pageRepository.GetPublishedPagesAsync();
        foreach (var page in pages)
        {
            entries.Add(new SitemapEntry
            {
                Url = $"{_baseUrl}{page.Path}",
                LastModified = page.ModifiedUtc,
                ChangeFrequency = GetChangeFrequency(page),
                Priority = CalculatePriority(page)
            });
        }

        // 添加页面集项目(博客帖子、产品等)
        var pageSets = await _pageSetRepository.GetAllAsync();
        foreach (var pageSet in pageSets)
        {
            var items = await _pageSetRepository.GetItemsAsync(pageSet.Id);
            foreach (var item in items)
            {
                var url = GenerateUrl(pageSet.UrlPattern, item);
                entries.Add(new SitemapEntry
                {
                    Url = url,
                    LastModified = item.ModifiedUtc,
                    ChangeFrequency = ChangeFrequency.Weekly,
                    Priority = 0.6m
                });
            }
        }

        return entries;
    }

    private decimal CalculatePriority(Page page)
    {
        // 首页最高优先级
        if (page.Depth == 0) return 1.0m;

        // 按深度递减
        return Math.Max(0.5m, 1.0m - (page.Depth * 0.1m));
    }
}

页面树API

REST 端点

GET    /api/pages                    # 根页面
GET    /api/pages/{id}               # 单个页面
GET    /api/pages/{id}/children      # 子页面
GET    /api/pages/path/{*path}       # 按URL路径获取页面
GET    /api/pages/tree               # 完整页面树
GET    /api/sitemap.xml              # XML站点地图
GET    /api/sitemap.json             # JSON站点地图

页面树响应

{
  "data": {
    "id": "page-123",
    "title": "关于我们",
    "slug": "about",
    "path": "/about",
    "template": "内容模板",
    "depth": 1,
    "order": 2,
    "children": [
      {
        "id": "page-456",
        "title": "我们的团队",
        "slug": "team",
        "path": "/about/team",
        "template": "团队模板",
        "children": []
      },
      {
        "id": "page-789",
        "title": "职业发展",
        "slug": "careers",
        "path": "/about/careers",
        "template": "内容模板",
        "children": []
      }
    ]
  },
  "breadcrumbs": [
    { "title": "首页", "path": "/" },
    { "title": "关于我们", "path": "/about" }
  ]
}

最佳实践

页面结构

模式 何时使用
扁平结构 简单网站,页面少
2级层次结构 大多数企业网站
深层层次结构 文档、大型目录
页面集 博客、作品集、团队页面

模板设计

做:
- 保持区域语义化(头部、主要内容、侧边栏)
- 允许灵活部件放置
- 从基础模板继承公共区域
- 提供合理的默认值

不做:
- 创建过于具体的模板
- 在模板中硬编码布局
- 混合内容和呈现关注点
- 创建深层模板继承链

相关技能

  • navigation-architecture - 菜单和面包屑设计
  • url-routing-patterns - URL结构和路由
  • content-type-modeling - 页面作为内容类型