Files
novalon-website/docs/superpowers/plans/2026-07-01-novalon-cms-system.md
T
张翔 636bc4ecde docs(test): 添加设计文档、测试规范与 E2E 测试套件
- 新增 ADR 架构决策记录 (Design DNA 集成与深化)
- 新增 CMS 系统设计文档
- 新增实施计划文档 (Phase1-3)
- 新增 Bain 品牌升级设计规格
- 新增 E2E 分层测试套件 (P1-P4)
- 新增视觉回归测试配置
- 新增光效分析、视觉验证等辅助脚本
- 更新验收测试报告
2026-07-07 06:54:25 +08:00

22 KiB
Raw Blame History

Novalon CMS 自研系统实现计划

面向 AI 代理的工作者: 必需子技能:使用 superpowers:subagent-driven-development(推荐)或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(- [ ])语法来跟踪进度。

目标: 构建与 Novalon 技术栈深度融合的自研 Headless CMS 系统,实现内容模型定义、内容管理、动态页面渲染、主题配置等核心能力。

架构: 采用 Broadleaf CMS 核心设计思想(ContentModel + ContentItem + ContentZone + ThemeField),基于 Java 21 + Spring Boot + PostgreSQL 构建后端服务,React + ProLayout 构建管理后台,Next.js 前端通过统一 SDK 接入。前端优先实现 SDK 与动态渲染层,后端 API 按接口契约并行开发。

技术栈:

  • 后端:Java 21 + Spring Boot WebFlux + PostgreSQL + Flyway + Spring Security
  • 管理端:React 18 + ProLayout + Zustand + Ant Design 5(对齐 novalon-manage-system
  • 前端网站:Next.js 14 + TypeScript + ISR/SSG
  • 数据校验:Zod(前端)+ Jakarta Validation(后端)

一、系统架构总览

1.1 整体架构图

┌─────────────────────────────────────────────────────────────┐
│                     前端展示层(Website)                     │
│              Next.js 14 + CMS SDK + 动态渲染器                │
└──────────────────────────────┬──────────────────────────────┘
                               │ RESTful API
┌──────────────────────────────▼──────────────────────────────┐
│                    CMS 服务层(Backend                      │
│  Java 21 + Spring Boot WebFlux + PostgreSQL + Flyway         │
│                                                             │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐   │
│  │ 内容模型 │ │ 内容项   │ │ 内容区域 │ │ 主题配置    │   │
│  │ 管理     │ │ 管理     │ │ 管理     │ │ 管理        │   │
│  └──────────┘ └──────────┘ └──────────┘ └─────────────┘   │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐   │
│  │ 媒体资源 │ │ 版本管理 │ │ 审计日志 │ │ 权限/SSO    │   │
│  │ 管理     │ │ 与草稿   │ │          │ │ 集成        │   │
│  └──────────┘ └──────────┘ └──────────┘ └─────────────┘   │
└──────────────────────────────┬──────────────────────────────┘
                               │
┌──────────────────────────────▼──────────────────────────────┐
│                    管理后台(Admin)                         │
│     React 18 + ProLayout + Zustand + Ant Design 5           │
│     (对齐 novalon-manage-system 架构规范)                   │
└─────────────────────────────────────────────────────────────┘

1.2 核心领域模型(源自 Broadleaf CMS 设计)

模型 表名 职责 对应 Broadleaf 概念
ContentModel cms_content_model 定义内容类型的 schema(字段、类型、校验) ContentModel
ContentItem cms_content_item 实际的内容数据,基于 model 动态字段 ContentItem
ContentZone cms_content_zone 页面中的可编辑区域定义 ContentZone
ThemeConfig cms_theme_config 站点主题、设置、SEO 等配置 ThemeField
MediaAsset cms_media_asset 媒体资源管理 -
ContentVersion cms_content_version 内容版本与草稿 -
AuditLog cms_audit_log 操作审计日志 -

二、文件结构设计

2.1 当前项目(novalon-website)新增文件

src/
├── lib/
│   └── cms/                    # CMS 前端 SDK
│       ├── types.ts            # 类型定义(ContentModel/ContentItem 等)
│       ├── client.ts           # API 客户端封装
│       ├── renderer.ts         # 内容渲染工具函数
│       └── index.ts            # barrel 导出
├── components/
│   └── cms/                     # CMS 渲染组件
│       ├── ContentRenderer.tsx # 动态内容渲染器
│       ├── SectionRenderer.tsx # Section 级渲染器(ContentZone
│       ├── FieldRenderer.tsx   # 字段级渲染器
│       └── index.ts
└── app/
    └── api/
        └── cms/                 # 前端 BFF 层(可选)
            └── [...path]/route.ts

2.2 后端服务(novalon-cms,独立项目)

novalon-cms/
├── cms-gateway/        # API 网关模块
├── cms-common/         # 公共工具模块
├── cms-db/             # 数据访问层(实体 + Repository
├── cms-content/        # 内容管理模块(model/item/zone
├── cms-media/          # 媒体资源模块
├── cms-theme/          # 主题配置模块
├── cms-admin/          # 管理端 API
└── cms-sys/            # 系统管理(用户/权限/审计)

2.3 管理后台(novalon-manage-system 扩展)

src/
├── pages/
│   └── cms/
│       ├── content-model/    # 内容模型管理
│       ├── content-item/     # 内容项管理
│       ├── content-zone/     # 内容区域管理
│       ├── media/            # 媒体库
│       └── theme/            # 主题配置
├── stores/
│   └── cms.ts                # CMS 状态管理
└── services/
    └── cms.ts                # CMS API 服务

三、阶段划分与里程碑

阶段一:前端 SDK + 动态渲染(当前项目,立即启动)

目标: 在当前 Next.js 项目中建立 CMS 接入层,定义完整的类型系统和渲染架构,为后端 API 开发提供契约。

交付物:

  • CMS 类型定义系统
  • API Client SDK(带 mock 数据支持)
  • 动态 Section 渲染器
  • 案例模块迁移试点(从 constants → CMS 数据结构)

阶段二:后端核心服务(Java 团队并行)

目标: 实现 CMS 核心数据模型和 CRUD API。

交付物:

  • 数据库表结构 + Flyway 迁移脚本
  • ContentModel CRUD API
  • ContentItem CRUD API + 版本管理
  • ContentZone API
  • 权限集成 + 审计日志

阶段三:管理后台开发

目标: 在 novalon-manage-system 中扩展 CMS 管理模块。

交付物:

  • 内容模型可视化编辑器
  • 内容项编辑器(动态表单)
  • 媒体资源管理
  • 主题配置面板

阶段四:全链路联调 + 内容迁移

目标: 前后端打通,完成所有内容模块迁移。

交付物:

  • 全模块 CMS 接入
  • 内容迁移脚本
  • ISR/SSG 缓存策略
  • 上线

四、详细任务清单

任务 1CMS 类型系统定义

文件:

  • 创建:src/lib/cms/types.ts
  • 创建:src/lib/cms/index.ts

内容: 定义以下核心类型

// 字段类型枚举
export type FieldType = 
  | 'text'           // 单行文本
  | 'textarea'       // 多行文本
  | 'richtext'       // 富文本
  | 'number'         // 数字
  | 'boolean'        // 布尔
  | 'date'           // 日期
  | 'datetime'       // 日期时间
  | 'image'          // 图片
  | 'media'          // 媒体资源
  | 'reference'      // 引用其他内容项
  | 'references'     // 引用多个内容项
  | 'json'           // JSON 结构
  | 'array'          // 数组
  | 'object';        // 嵌套对象

// 字段定义
export interface FieldDefinition {
  name: string;
  type: FieldType;
  label: string;
  required?: boolean;
  description?: string;
  placeholder?: string;
  defaultValue?: unknown;
  validation?: {
    min?: number;
    max?: number;
    pattern?: string;
    custom?: string;
  };
  options?: Array<{ label: string; value: string | number | boolean }>;
  referenceModel?: string;  // reference 类型关联的 model code
  ui?: {
    component?: string;      // 指定 UI 组件
    width?: 'full' | 'half' | 'third';
    helpText?: string;
  };
  fields?: FieldDefinition[]; // object/array 类型的嵌套字段
}

// 内容模型
export interface ContentModel {
  id: string;
  code: string;               // 唯一标识,如 'case-study'
  name: string;
  description?: string;
  fields: FieldDefinition[];
  isPageType: boolean;        // 是否为页面类型(支持 URL 路由)
  urlPattern?: string;        // URL 模式,如 '/cases/{slug}'
  hasVersions: boolean;       // 是否启用版本管理
  hasDraft: boolean;          // 是否启用草稿
  icon?: string;
  createdAt: string;
  updatedAt: string;
}

// 内容状态
export type ContentStatus = 'draft' | 'review' | 'published' | 'archived';

// 内容项
export interface ContentItem {
  id: string;
  modelId: string;
  modelCode: string;
  title: string;
  slug?: string;
  status: ContentStatus;
  data: Record<string, unknown>;  // 动态字段数据,结构由 model 定义
  version: number;
  publishedAt?: string;
  createdBy: string;
  updatedBy: string;
  createdAt: string;
  updatedAt: string;
}

// 内容区域
export interface ContentZone {
  id: string;
  code: string;               // 区域唯一标识,如 'home-hero'
  name: string;
  description?: string;
  pageCode?: string;          // 所属页面
  allowedModels: string[];    // 允许的内容模型 codes
  items: Array<{
    itemId: string;
    item?: ContentItem;
    sortOrder: number;
    config?: Record<string, unknown>; // 区域级配置
  }>;
}

// 主题配置
export interface ThemeConfig {
  id: string;
  siteName: string;
  siteDescription: string;
  logo?: string;
  favicon?: string;
  colors: {
    primary: string;
    secondary: string;
    accent: string;
    background: string;
    text: string;
  };
  seo: {
    defaultTitle: string;
    defaultDescription: string;
    defaultKeywords: string;
    ogImage?: string;
  };
  social: {
    wechat?: string;
    weibo?: string;
    linkedin?: string;
    github?: string;
  };
  settings: Record<string, unknown>; // 其他自定义设置
}

// 分页查询参数
export interface ContentQueryParams {
  modelCode: string;
  status?: ContentStatus;
  page?: number;
  pageSize?: number;
  sortBy?: string;
  sortOrder?: 'asc' | 'desc';
  filters?: Record<string, string | number | boolean>;
  search?: string;
}

// 分页结果
export interface PaginatedResult<T> {
  items: T[];
  total: number;
  page: number;
  pageSize: number;
  totalPages: number;
}

任务 2CMS API Client SDK

文件:

  • 创建:src/lib/cms/client.ts
  • 修改:src/lib/cms/index.ts

内容: 封装 CMS API 客户端,支持真实 API 和 mock 模式

// 配置
interface CmsClientConfig {
  baseUrl: string;
  apiKey?: string;
  timeout?: number;
  mockMode?: boolean;  // 开发阶段使用 mock 数据
}

// 客户端类
class CmsClient {
  constructor(config: CmsClientConfig) {}
  
  // 内容模型相关
  async getModels(): Promise<ContentModel[]> {}
  async getModel(code: string): Promise<ContentModel> {}
  
  // 内容项相关
  async getItems(params: ContentQueryParams): Promise<PaginatedResult<ContentItem>> {}
  async getItem(id: string): Promise<ContentItem> {}
  async getItemBySlug(modelCode: string, slug: string): Promise<ContentItem> {}
  
  // 内容区域相关
  async getZone(code: string): Promise<ContentZone> {}
  async getZonesByPage(pageCode: string): Promise<ContentZone[]> {}
  
  // 主题配置相关
  async getThemeConfig(): Promise<ThemeConfig> {}
  
  // 工具方法
  async withType<T extends Record<string, unknown>>(
    item: ContentItem
  ): Promise<T> {}
}

任务 3:动态 Section 渲染器(ContentZone 实现)

文件:

  • 创建:src/components/cms/SectionRenderer.tsx
  • 创建:src/components/cms/FieldRenderer.tsx
  • 创建:src/components/cms/ContentRenderer.tsx
  • 创建:src/components/cms/index.ts

核心设计思想:

  • ContentZone = 页面上的一个可编辑区域
  • 每个 Zone 包含多个 ContentItem
  • 每个 ContentItem 根据其 model type 选择对应的渲染组件
// 组件注册表
interface SectionComponentRegistry {
  [modelCode: string]: React.ComponentType<{ data: any; config?: any }>;
}

// SectionRenderer: 渲染单个 ContentZone
function SectionRenderer({ zoneCode, fallback }: { 
  zoneCode: string; 
  fallback?: React.ReactNode;
}) {}

// ContentRenderer: 渲染单个 ContentItem
function ContentRenderer({ item }: { item: ContentItem }) {}

// FieldRenderer: 渲染单个字段
function FieldRenderer({ 
  field, value 
}: { 
  field: FieldDefinition; 
  value: unknown;
}) {}

任务 4:案例模块迁移试点

目标: 将现有的案例数据从 constants/cases.ts 迁移为 CMS 数据结构,验证类型系统和渲染器的正确性。

文件:

  • 修改:src/lib/cms/mock-data.ts(新建 mock 数据)
  • 修改:src/app/(marketing)/cases/cases-content-v1.tsx
  • 修改:src/app/(marketing)/cases/[slug]/client.tsx

迁移内容:

  • 定义 case-study 内容模型(对应 CaseStudy 接口)
  • 将 6 个案例转为 ContentItem 格式
  • 列表页和详情页改为从 CMS Client 获取数据
  • 保留 mock 模式,后端 API 完成后无缝切换

任务 5:后端 API 接口契约

文件:

  • 创建:docs/cms/api-contract.md

核心 API 列表:

模块 Method Path 说明
内容模型 GET /api/cms/models 获取所有内容模型
内容模型 GET /api/cms/models/{code} 获取单个模型定义
内容模型 POST /api/cms/models 创建内容模型
内容模型 PUT /api/cms/models/{code} 更新内容模型
内容项 GET /api/cms/items 分页查询内容项
内容项 GET /api/cms/items/{id} 获取内容项详情
内容项 GET /api/cms/items/slug/{modelCode}/{slug} 按 slug 获取
内容项 POST /api/cms/items 创建内容项
内容项 PUT /api/cms/items/{id} 更新内容项
内容项 POST /api/cms/items/{id}/publish 发布内容
内容项 POST /api/cms/items/{id}/unpublish 下架内容
内容区域 GET /api/cms/zones/{code} 获取区域内容
内容区域 PUT /api/cms/zones/{code} 更新区域配置
主题配置 GET /api/cms/theme 获取主题配置
主题配置 PUT /api/cms/theme 更新主题配置
媒体资源 GET /api/cms/media 媒体列表
媒体资源 POST /api/cms/media/upload 上传媒体

五、数据模型详细设计

5.1 cms_content_model(内容模型表)

字段 类型 说明
id bigint PK 主键
code varchar(100) UNIQUE 模型唯一编码
name varchar(200) 模型名称
description varchar(500) 描述
fields_json jsonb 字段定义 JSON
is_page_type boolean 是否为页面类型
url_pattern varchar(200) URL 模式
has_versions boolean 是否启用版本
has_draft boolean 是否启用草稿
icon varchar(50) 图标
created_by varchar(100) 创建人
updated_by varchar(100) 更新人
created_at timestamp 创建时间
updated_at timestamp 更新时间
deleted boolean 逻辑删除

5.2 cms_content_item(内容项表)

字段 类型 说明
id bigint PK 主键
model_id bigint FK 关联模型 ID
model_code varchar(100) 冗余模型编码
title varchar(500) 内容标题
slug varchar(200) URL slug
status varchar(20) 状态:draft/review/published/archived
data_json jsonb 内容数据 JSON
version int 当前版本号
published_at timestamp 发布时间
created_by varchar(100) 创建人
updated_by varchar(100) 更新人
created_at timestamp 创建时间
updated_at timestamp 更新时间
deleted boolean 逻辑删除

索引:(model_code, status, created_at)(model_code, slug) 唯一索引

5.3 cms_content_version(内容版本表)

字段 类型 说明
id bigint PK 主键
item_id bigint FK 内容项 ID
version int 版本号
data_json jsonb 版本数据快照
status varchar(20) 版本状态
change_log varchar(500) 变更说明
created_by varchar(100) 创建人
created_at timestamp 创建时间

5.4 cms_content_zone(内容区域表)

字段 类型 说明
id bigint PK 主键
code varchar(100) UNIQUE 区域编码
name varchar(200) 区域名称
description varchar(500) 描述
page_code varchar(100) 所属页面
allowed_models varchar(500) 允许的模型 codes(逗号分隔)
items_json jsonb 区域内内容项配置(顺序、附加配置)
created_at timestamp 创建时间
updated_at timestamp 更新时间

5.5 cms_theme_config(主题配置表)

字段 类型 说明
id bigint PK 主键(单表单记录,id=1
config_json jsonb 完整配置 JSON
updated_by varchar(100) 更新人
updated_at timestamp 更新时间

5.6 cms_media_asset(媒体资源表)

字段 类型 说明
id bigint PK 主键
name varchar(200) 文件名称
path varchar(500) 存储路径
url varchar(500) 访问 URL
mime_type varchar(100) MIME 类型
size bigint 文件大小(字节)
width int 图片宽度
height int 图片高度
alt varchar(200) 替代文本
storage_type varchar(20) 存储类型:local/oss/s3
created_by varchar(100) 创建人
created_at timestamp 创建时间

5.7 cms_audit_log(审计日志表)

字段 类型 说明
id bigint PK 主键
module varchar(50) 模块:model/item/zone/theme/media
target_id bigint 操作对象 ID
action varchar(50) 操作:create/update/delete/publish/unpublish
operator varchar(100) 操作人
before_json jsonb 操作前数据
after_json jsonb 操作后数据
ip varchar(50) IP 地址
user_agent varchar(500) User Agent
created_at timestamp 操作时间

六、安全与权限设计

6.1 权限模型

角色 权限说明
超级管理员 所有权限
CMS 管理员 内容模型管理、内容管理、用户管理
内容编辑 内容创建、编辑、提交审核
内容审核 内容审核、发布、下架
访客 仅查看(前端 API

6.2 API 安全

  • 管理端 API:走现有 SSO + 权限体系
  • 前端 API:仅读取 published 状态内容,无需鉴权(或 API Key 限流)
  • 敏感操作:写入操作必须有审计日志
  • 数据隔离:按业务线/租户隔离(预留)

七、性能优化策略

7.1 前端侧

  • ISR/SSG:内容页使用 Next.js ISR,内容变更时触发 revalidate
  • 缓存策略
    • 内容列表:10 分钟缓存 + stale-while-revalidate
    • 内容详情:1 小时缓存,发布时主动失效
    • 主题配置:构建时注入,运行时热更新
  • 图片优化:使用 Next.js Image + CDN 加速

7.2 后端侧

  • 数据库索引:按查询模式建立合理索引
  • Redis 缓存:热点内容数据缓存
  • 读写分离:读操作走从库
  • CDN 加速:媒体资源走 CDN

八、与现有系统的集成

8.1 用户/权限集成

  • 复用 novalon-manage-system 的用户体系和权限框架
  • SSO 单点登录
  • 统一的角色/权限管理界面

8.2 审计集成

  • 接入现有审计日志系统
  • CMS 操作日志同步到统一审计平台

8.3 监控集成

  • 接入现有监控体系(Prometheus + Grafana
  • 关键指标:API 响应时间、错误率、内容发布量

九、风险与应对

风险 概率 影响 应对策略
动态字段查询性能 合理设计索引,必要时引入 ES 做全文检索
富文本编辑器选型 预研 Tiptap/Lexical,留接口抽象层可替换
内容迁移成本 开发迁移脚本,分批迁移,先迁移更新频繁的模块
管理后台开发量 优先开发核心功能,可视化编辑器可后置,先用动态表单

十、里程碑验收标准

阶段一验收(前端 SDK

  • 完整的 TypeScript 类型定义
  • CMS Client SDKmock 模式可用)
  • 动态 Section 渲染器(支持 3 种以上内容类型)
  • 案例模块试点完成(列表 + 详情)
  • 单元测试覆盖率 ≥ 80%

阶段二验收(后端核心)

  • 7 张核心表 + Flyway 迁移脚本
  • 30+ 个 RESTful API
  • 内容版本管理(草稿/发布/回滚)
  • 审计日志完整
  • 权限集成完成
  • API 单元测试覆盖率 ≥ 80%

阶段三验收(管理后台)

  • 内容模型可视化编辑器
  • 动态表单内容编辑器
  • 媒体资源管理(上传/列表/删除)
  • 主题配置面板
  • 操作审计日志查看

阶段四验收(全链路)

  • 所有内容模块迁移完成(案例/新闻/产品/解决方案/服务)
  • 前后端联调通过
  • 性能达标(LCP < 2s
  • 安全扫描通过
  • 内容迁移脚本验证通过