docs: SiteForge 规划文档基线 + 纵向切片设计规格 V1
- V3.0 总体方案、主题与板块设计、实施计划 - cms 现状差距分析 V2.0(V1.0 已标注作废)与复用评估 V1.0 - 纵向切片设计规格(路线 C:全新架构 + 白名单资产移植) - .gitignore 先行(storage/artifacts/env 永不入库) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
# 依赖与构建产物
|
||||
node_modules/
|
||||
dist/
|
||||
.artifacts/
|
||||
artifacts/
|
||||
coverage/
|
||||
.turbo/
|
||||
|
||||
# 试点数据与本地状态(WXR/媒体副本、数据库、密钥——绝不入库)
|
||||
storage/
|
||||
.data/
|
||||
.env
|
||||
.env.*
|
||||
*.local
|
||||
|
||||
# 日志与临时文件
|
||||
*.log
|
||||
tmp/
|
||||
.DS_Store
|
||||
@@ -0,0 +1,900 @@
|
||||
# SiteForge 主题与板块设计方案
|
||||
|
||||
> 版本:V1.0
|
||||
> 日期:2026-10-20
|
||||
> 目标:支持每个网站拥有独立设计,同时让内容可以在后台结构化编辑并生成纯静态页面。
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计结论
|
||||
|
||||
主题和板块必须解耦:
|
||||
|
||||
- **主题(Theme)**负责页面结构、视觉风格、HTML、CSS、动画和响应式实现。
|
||||
- **板块(Block)**负责内容字段及其顺序,例如标题、图片、按钮、产品参数、FAQ。
|
||||
- **模板(Template)**规定一类页面默认由哪些区域组成,以及允许使用哪些板块。
|
||||
- **页面(Page)**保存所选模板和实际板块数据。
|
||||
|
||||
推荐模式是:
|
||||
|
||||
```text
|
||||
统一板块数据协议 + 每个主题自己的板块渲染器
|
||||
```
|
||||
|
||||
例如后台都保存 `hero` 数据,但汽车站可以显示全屏视频,工业站可以显示左文右图。两者共享内容语义,不共享强制布局。
|
||||
|
||||
V1 不做任意坐标、任意嵌套的低代码编辑器,只提供:
|
||||
|
||||
- 选择板块。
|
||||
- 表单编辑字段。
|
||||
- 调整板块顺序。
|
||||
- 启用或隐藏板块。
|
||||
- 选择少量经过主题声明的样式变体。
|
||||
- PC/移动端静态预览。
|
||||
|
||||
这样既能快速维护,又不会让自由配置破坏设计、响应式和 SEO。
|
||||
|
||||
---
|
||||
|
||||
## 2. 四层结构
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
CONTENT[内容:产品/文章/页面/媒体]
|
||||
BLOCK[板块实例:type + data + settings]
|
||||
TEMPLATE[页面模板:区域与板块约束]
|
||||
THEME[主题:组件、样式、交互]
|
||||
HTML[静态 HTML/CSS/JS]
|
||||
|
||||
CONTENT --> BLOCK
|
||||
BLOCK --> TEMPLATE
|
||||
TEMPLATE --> THEME
|
||||
THEME --> HTML
|
||||
```
|
||||
|
||||
### 2.1 内容层
|
||||
|
||||
保存可复用的业务数据,例如产品名称、参数、文章正文和媒体资源。内容不应该写死在主题代码里。
|
||||
|
||||
### 2.2 板块层
|
||||
|
||||
保存某个页面中的展示内容和顺序。板块数据尽量不包含颜色、像素、CSS 类名等主题实现细节。
|
||||
|
||||
### 2.3 模板层
|
||||
|
||||
定义首页、产品详情、新闻详情、普通页面等页面类型及允许的区域。模板可以自动插入由业务数据驱动的系统区域。
|
||||
|
||||
### 2.4 主题层
|
||||
|
||||
每个主题提供自己的 Astro 页面、组件、样式和板块渲染器,最终生成静态文件。
|
||||
|
||||
---
|
||||
|
||||
## 3. 板块分类
|
||||
|
||||
### 3.1 全局板块
|
||||
|
||||
全站复用,单独管理:
|
||||
|
||||
- Header
|
||||
- Footer
|
||||
- 顶部通知条
|
||||
- 全局询价 CTA
|
||||
- 联系方式
|
||||
- 社交媒体链接
|
||||
- Cookie/隐私提示
|
||||
|
||||
修改全局板块后,会重建所有引用它的页面;V1 可以直接触发该站全量构建。
|
||||
|
||||
### 3.2 页面内容板块
|
||||
|
||||
由管理员在页面中新增、排序和编辑:
|
||||
|
||||
- Hero
|
||||
- Rich Text
|
||||
- Image + Text
|
||||
- Image Gallery
|
||||
- Video
|
||||
- Feature List
|
||||
- Statistics
|
||||
- Logo/Brand List
|
||||
- Product Grid
|
||||
- Article List
|
||||
- Specification Table
|
||||
- Download List
|
||||
- FAQ
|
||||
- Testimonials
|
||||
- CTA
|
||||
- Contact Information
|
||||
- Map Embed
|
||||
|
||||
### 3.3 模板系统板块
|
||||
|
||||
由模板根据当前内容自动生成,通常不允许页面编辑者删除:
|
||||
|
||||
- 面包屑
|
||||
- 产品主信息
|
||||
- 产品参数
|
||||
- 文章标题、日期和正文
|
||||
- 分类列表与分页
|
||||
- 相关推荐
|
||||
- SEO Head
|
||||
|
||||
管理员可以在允许范围内控制显示、顺序或样式变体,但不直接维护其核心业务数据。
|
||||
|
||||
### 3.4 站点专属板块
|
||||
|
||||
某些页面效果只属于一个站点,可以由主题声明自定义板块,例如:
|
||||
|
||||
```text
|
||||
vehicle-360-view
|
||||
charging-calculator
|
||||
factory-process-timeline
|
||||
dealer-map
|
||||
```
|
||||
|
||||
站点专属板块仍需提供数据 schema 和后台表单定义,不能只在代码中写死内容。
|
||||
|
||||
### 3.5 Legacy HTML 板块
|
||||
|
||||
用于暂时无法结构化的历史内容:
|
||||
|
||||
- 只接受清洗后的 HTML。
|
||||
- 删除脚本、事件属性和危险 URL。
|
||||
- 使用隔离样式容器。
|
||||
- 后台醒目标记为“待结构化”。
|
||||
- 不能作为新页面的默认编辑方式。
|
||||
|
||||
---
|
||||
|
||||
## 4. 板块数据协议
|
||||
|
||||
### 4.1 板块实例
|
||||
|
||||
```ts
|
||||
export interface BlockInstance<TData = Record<string, unknown>> {
|
||||
id: string;
|
||||
type: string;
|
||||
schemaVersion: number;
|
||||
variant?: string;
|
||||
data: TData;
|
||||
settings?: {
|
||||
anchorId?: string;
|
||||
themeMode?: 'default' | 'light' | 'dark';
|
||||
spacing?: 'none' | 'small' | 'medium' | 'large';
|
||||
};
|
||||
visibility: {
|
||||
enabled: boolean;
|
||||
locales?: string[];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 页面内容示例
|
||||
|
||||
```json
|
||||
{
|
||||
"contentId": "page_home",
|
||||
"templateKey": "home",
|
||||
"blocks": [
|
||||
{
|
||||
"id": "block_hero_01",
|
||||
"type": "hero",
|
||||
"schemaVersion": 1,
|
||||
"variant": "image-right",
|
||||
"data": {
|
||||
"eyebrow": "New Energy Vehicles",
|
||||
"title": "Build Your Next Journey",
|
||||
"description": "A short introduction.",
|
||||
"mediaId": "asset_1001",
|
||||
"primaryAction": {
|
||||
"label": "View Products",
|
||||
"href": "/products/"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"spacing": "large",
|
||||
"themeMode": "dark"
|
||||
},
|
||||
"visibility": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 内容和样式边界
|
||||
|
||||
建议保存在板块数据中的字段:
|
||||
|
||||
- 标题、描述和按钮文案。
|
||||
- 媒体资源引用。
|
||||
- 内部/外部链接。
|
||||
- 产品、文章、分类等内容引用。
|
||||
- 允许的语义变体,例如 `featured`、`compact`。
|
||||
|
||||
不建议保存:
|
||||
|
||||
- 任意 CSS。
|
||||
- Tailwind/CSS 类名。
|
||||
- 像素坐标。
|
||||
- 随意输入的颜色值。
|
||||
- 主题组件文件路径。
|
||||
- 可执行 JavaScript。
|
||||
|
||||
颜色、字体和间距默认由主题控制。如果确实需要运营配置,只允许主题 manifest 中声明的有限选项。
|
||||
|
||||
---
|
||||
|
||||
## 5. 板块定义与表单生成
|
||||
|
||||
每个板块类型包含两份声明:
|
||||
|
||||
1. `schema`:数据校验规则。
|
||||
2. `uiSchema`:后台如何展示编辑表单。
|
||||
|
||||
### 5.1 Hero Schema 示例
|
||||
|
||||
```json
|
||||
{
|
||||
"$id": "siteforge://blocks/hero/v1",
|
||||
"type": "object",
|
||||
"required": ["title"],
|
||||
"properties": {
|
||||
"eyebrow": { "type": "string", "maxLength": 80 },
|
||||
"title": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"description": { "type": "string", "maxLength": 500 },
|
||||
"mediaId": { "type": "string" },
|
||||
"primaryAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": { "type": "string", "maxLength": 40 },
|
||||
"href": { "type": "string" }
|
||||
},
|
||||
"required": ["label", "href"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 UI Schema 示例
|
||||
|
||||
```json
|
||||
{
|
||||
"title": { "widget": "text", "label": "主标题" },
|
||||
"description": { "widget": "textarea", "label": "说明" },
|
||||
"mediaId": { "widget": "media-picker", "label": "主视觉" },
|
||||
"primaryAction.href": { "widget": "link-picker", "label": "按钮链接" }
|
||||
}
|
||||
```
|
||||
|
||||
管理后台根据这些声明生成表单,不需要为每个主题重复开发一套内容编辑页面。
|
||||
|
||||
推荐使用 JSON Schema 作为跨前后端协议,并使用 Ajv 校验。主题内可以生成对应 TypeScript 类型,避免重复维护接口。
|
||||
|
||||
---
|
||||
|
||||
## 6. 主题协议
|
||||
|
||||
### 6.1 主题清单
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "automotive-premium",
|
||||
"name": "Automotive Premium",
|
||||
"version": "1.0.0",
|
||||
"engine": "astro",
|
||||
"siteConfigSchema": "./schemas/site-config.schema.json",
|
||||
"templates": {
|
||||
"home": {
|
||||
"entry": "src/templates/HomePage.astro",
|
||||
"allowedBlocks": ["hero", "feature-list", "product-grid", "cta"],
|
||||
"requiredBlocks": ["hero"],
|
||||
"maxPerType": { "hero": 1 }
|
||||
},
|
||||
"product": {
|
||||
"entry": "src/templates/ProductDetail.astro",
|
||||
"allowedBlocks": ["gallery", "specification-table", "download-list", "faq", "cta"]
|
||||
},
|
||||
"page": {
|
||||
"entry": "src/templates/GenericPage.astro",
|
||||
"allowedBlocks": ["hero", "rich-text", "image-text", "gallery", "faq", "cta"]
|
||||
}
|
||||
},
|
||||
"blocks": {
|
||||
"hero": {
|
||||
"renderer": "src/blocks/HeroBlock.astro",
|
||||
"schema": "siteforge://blocks/hero/v1",
|
||||
"variants": ["fullscreen", "image-right", "minimal"]
|
||||
},
|
||||
"product-grid": {
|
||||
"renderer": "src/blocks/ProductGridBlock.astro",
|
||||
"schema": "siteforge://blocks/product-grid/v1",
|
||||
"variants": ["cards", "editorial"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 主题目录
|
||||
|
||||
```text
|
||||
themes/automotive-premium/
|
||||
theme.json
|
||||
schemas/
|
||||
site-config.schema.json
|
||||
src/
|
||||
templates/
|
||||
HomePage.astro
|
||||
ProductDetail.astro
|
||||
ArticleDetail.astro
|
||||
GenericPage.astro
|
||||
blocks/
|
||||
HeroBlock.astro
|
||||
RichTextBlock.astro
|
||||
ProductGridBlock.astro
|
||||
FaqBlock.astro
|
||||
components/
|
||||
Header.astro
|
||||
Footer.astro
|
||||
Breadcrumb.astro
|
||||
layouts/
|
||||
BaseLayout.astro
|
||||
styles/
|
||||
tokens.css
|
||||
global.css
|
||||
lib/
|
||||
block-renderers.ts
|
||||
public/
|
||||
```
|
||||
|
||||
### 6.3 不使用主题继承
|
||||
|
||||
V1 不建议建立复杂的父主题/子主题覆盖机制。公共能力通过普通包复用:
|
||||
|
||||
```text
|
||||
packages/theme-runtime
|
||||
packages/seo-components
|
||||
packages/block-contracts
|
||||
packages/media-components
|
||||
```
|
||||
|
||||
每个主题仍然明确拥有自己的模板和 CSS。这样升级公共包时更可控,也避免多层覆盖难以追踪。
|
||||
|
||||
### 6.4 四层组件化复用架构
|
||||
|
||||
为了提高新主题和新网站的开发速度,组件按复用程度分为四层:
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
C1[第一层:数据契约与工具]
|
||||
C2[第二层:无样式基础组件]
|
||||
C3[第三层:业务逻辑与 Headless 组件]
|
||||
C4[第四层:主题展示组件]
|
||||
PAGE[页面模板]
|
||||
|
||||
C1 --> C2
|
||||
C1 --> C3
|
||||
C2 --> C4
|
||||
C3 --> C4
|
||||
C4 --> PAGE
|
||||
```
|
||||
|
||||
#### 第一层:数据契约与工具,完全复用
|
||||
|
||||
- Block、Page、Media、Menu、SEO 类型。
|
||||
- JSON Schema 和数据验证。
|
||||
- 内部链接解析。
|
||||
- 图片地址、`srcset` 和尺寸计算。
|
||||
- URL、Canonical、Hreflang 和结构化数据生成。
|
||||
- HTML 净化、日期格式化和多语言工具。
|
||||
|
||||
这一层不包含任何主题样式。
|
||||
|
||||
#### 第二层:无样式基础组件,高度复用
|
||||
|
||||
- Container
|
||||
- Grid
|
||||
- Stack
|
||||
- Media
|
||||
- Picture
|
||||
- Link
|
||||
- Button 基础行为
|
||||
- Dialog
|
||||
- Accordion
|
||||
- Tabs
|
||||
- Carousel 控制逻辑
|
||||
- Pagination
|
||||
|
||||
组件提供语义、可访问性和交互状态,不固定颜色、字体和视觉效果。主题通过 CSS、自定义属性和组合方式决定最终外观。
|
||||
|
||||
#### 第三层:业务逻辑与 Headless 组件,高度复用
|
||||
|
||||
- 产品列表查询与分页。
|
||||
- 文章列表查询。
|
||||
- 产品参数分组。
|
||||
- 菜单树解析。
|
||||
- 面包屑生成。
|
||||
- FAQ 展开状态。
|
||||
- 表单校验和提交状态。
|
||||
- 搜索数据适配。
|
||||
- 相关推荐规则。
|
||||
|
||||
这类组件输出数据或状态,不直接决定最终 DOM 结构。例如 `createProductGridModel()` 负责得到产品卡片数据,汽车主题和工业主题分别决定如何渲染卡片。
|
||||
|
||||
#### 第四层:主题展示组件,按主题独立
|
||||
|
||||
- Header、Footer、Mega Menu。
|
||||
- Hero 的具体布局。
|
||||
- Product Card 的视觉结构。
|
||||
- 首页各板块的组合方式。
|
||||
- 动画、颜色、字体和响应式细节。
|
||||
|
||||
这一层允许完全不同,避免为了复用而把所有网站做成同一种风格。
|
||||
|
||||
### 6.5 公共组件包结构
|
||||
|
||||
```text
|
||||
packages/
|
||||
content-contracts/ # Page、Block、Product、Post 等类型
|
||||
block-contracts/ # 板块 schema、版本和迁移
|
||||
theme-runtime/ # 主题加载、模板解析、渲染上下文
|
||||
ui-primitives/ # 无样式基础组件
|
||||
headless-components/ # 菜单、分页、Tabs、Accordion 等逻辑
|
||||
content-resolvers/ # 产品/文章/分类引用解析
|
||||
media-components/ # Picture、Video、资源地址与 srcset
|
||||
seo-components/ # Meta、Canonical、Hreflang、JSON-LD
|
||||
form-runtime/ # 表单 schema、校验和提交适配
|
||||
design-tokens/ # 公共 token 协议,不存具体品牌值
|
||||
```
|
||||
|
||||
主题只引用公共包的正式入口,不能跨主题引用另一个主题内部文件。
|
||||
|
||||
```text
|
||||
允许:theme-a → packages/ui-primitives
|
||||
禁止:theme-a → themes/theme-b/src/components/ProductCard.astro
|
||||
```
|
||||
|
||||
如果多个主题确实重复使用一个展示组件,应先将其中的通用行为和结构抽到公共包,再由各主题提供外观;不要直接复制后形成多个无法同步的版本。
|
||||
|
||||
### 6.6 设计令牌
|
||||
|
||||
公共组件只使用语义化 token,不使用某个网站的品牌颜色:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--sf-color-primary: #1f4b7a;
|
||||
--sf-color-accent: #e8792e;
|
||||
--sf-color-text: #1b1f24;
|
||||
--sf-color-surface: #ffffff;
|
||||
--sf-radius-control: 0.5rem;
|
||||
--sf-space-section: clamp(4rem, 8vw, 8rem);
|
||||
--sf-container-width: 75rem;
|
||||
}
|
||||
```
|
||||
|
||||
每个主题覆盖这些 token,也可以增加自己的 token。公共包不得依赖只有某个主题才存在的 token。
|
||||
|
||||
### 6.7 组合优于大量 Variant
|
||||
|
||||
公共组件保持小而稳定,通过组合形成页面板块:
|
||||
|
||||
```astro
|
||||
<Section>
|
||||
<Container>
|
||||
<SplitLayout>
|
||||
<HeroContent data={block.data} />
|
||||
<ThemeHeroMedia media={media} />
|
||||
</SplitLayout>
|
||||
</Container>
|
||||
</Section>
|
||||
```
|
||||
|
||||
不要给一个公共 Hero 增加几十个布尔属性来适应所有网站,例如 `rounded`、`centered`、`overlay`、`video`、`reverse`、`compact` 的任意组合。稳定的数据协议可以复用,最终板块应由主题组合基础组件实现。
|
||||
|
||||
### 6.8 组件复用矩阵
|
||||
|
||||
| 能力 | 公共包复用 | 主题独立 |
|
||||
|---|---:|---:|
|
||||
| 数据类型与 Schema | 是 | 否 |
|
||||
| SEO Head | 是 | 可提供少量站点配置 |
|
||||
| Picture/srcset | 是 | 可控制画面比例和样式 |
|
||||
| 菜单树和展开逻辑 | 是 | Header 结构和动画独立 |
|
||||
| 产品查询与分页 | 是 | 产品卡片独立 |
|
||||
| FAQ 数据与交互状态 | 是 | 排版和图标独立 |
|
||||
| 表单校验与提交 | 是 | 字段布局和视觉独立 |
|
||||
| Hero 内容协议 | 是 | Hero 渲染完全独立 |
|
||||
| 页面模板 | 否 | 是 |
|
||||
| 品牌色、字体、间距 | 仅协议 | 是 |
|
||||
|
||||
### 6.9 组件版本与兼容
|
||||
|
||||
- 公共包遵循语义化版本。
|
||||
- 破坏性变更必须提供迁移说明或兼容适配层。
|
||||
- 主题 manifest 记录公共运行时的兼容范围。
|
||||
- 每个公共组件提供最小、完整、异常三个测试 fixture。
|
||||
- 公共组件升级后,自动构建所有示范主题并执行截图回归。
|
||||
- 发布 release 锁定公共包和主题版本,回滚时不能自动升级依赖。
|
||||
|
||||
### 6.10 组件预览与文档
|
||||
|
||||
建立独立的组件预览页,展示:
|
||||
|
||||
- 基础组件的状态和可访问性。
|
||||
- 每种板块的最小/完整数据。
|
||||
- 同一板块在不同主题中的效果。
|
||||
- 桌面、平板和手机断点。
|
||||
- 空数据、超长标题、图片缺失等异常状态。
|
||||
|
||||
预览页可以采用 Storybook 或项目内 Astro 组件目录。V1 的重点是可查看和自动截图,不强制依赖某个文档工具。
|
||||
|
||||
---
|
||||
|
||||
## 7. 模板约束
|
||||
|
||||
模板除了渲染页面,还负责约束后台可配置范围。
|
||||
|
||||
```ts
|
||||
export interface TemplateDefinition {
|
||||
key: string;
|
||||
contentTypes: string[];
|
||||
allowedBlocks: string[];
|
||||
requiredBlocks?: string[];
|
||||
maxPerType?: Record<string, number>;
|
||||
lockedRegions?: string[];
|
||||
}
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
- 首页必须有一个 Hero,最多一个。
|
||||
- 产品详情固定显示产品标题、价格/询价入口和核心参数。
|
||||
- FAQ、下载、CTA 可以由管理员添加、删除和排序。
|
||||
- SEO Head、Header、Footer 是锁定区域,不出现在自由排序列表里。
|
||||
|
||||
后台新增板块时,只显示当前主题、当前模板支持的类型和变体。
|
||||
|
||||
---
|
||||
|
||||
## 8. 数据库存储
|
||||
|
||||
推荐将板块实例按修订版本独立存储,而不是直接写入已发布页面。
|
||||
|
||||
```sql
|
||||
CREATE TABLE page_blocks (
|
||||
id UUID PRIMARY KEY,
|
||||
site_id UUID NOT NULL REFERENCES sites(id),
|
||||
revision_id UUID NOT NULL REFERENCES content_revisions(id),
|
||||
block_type TEXT NOT NULL,
|
||||
schema_version INTEGER NOT NULL,
|
||||
variant TEXT,
|
||||
position INTEGER NOT NULL,
|
||||
data JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
settings JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
visibility JSONB NOT NULL DEFAULT '{"enabled":true}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_page_blocks_revision_position
|
||||
ON page_blocks(revision_id, position);
|
||||
```
|
||||
|
||||
全局板块可以使用:
|
||||
|
||||
```text
|
||||
global_fragments
|
||||
global_fragment_revisions
|
||||
global_fragment_usages
|
||||
```
|
||||
|
||||
发布时锁定内容修订和全局板块修订,确保历史 release 可以准确回滚。
|
||||
|
||||
---
|
||||
|
||||
## 9. 后台编辑体验
|
||||
|
||||
### 9.1 页面编辑器布局
|
||||
|
||||
```text
|
||||
┌────────────────────────────────────────────────────────────┐
|
||||
│ 页面标题 / URL / 模板 / 保存 / 预览 / 发布 │
|
||||
├──────────────────────┬─────────────────────────────────────┤
|
||||
│ 板块列表 │ 当前板块表单 │
|
||||
│ │ │
|
||||
│ 1. Hero │ 标题 [________________] │
|
||||
│ 2. Product Grid │ 描述 [________________] │
|
||||
│ 3. FAQ │ 图片 [选择媒体] │
|
||||
│ 4. CTA │ 样式变体 [image-right ▼] │
|
||||
│ │ │
|
||||
│ [+ 添加板块] │ │
|
||||
└──────────────────────┴─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
首版功能:
|
||||
|
||||
- 点击新增板块。
|
||||
- 拖动调整纵向顺序。
|
||||
- 复制、隐藏和删除板块。
|
||||
- 编辑结构化字段。
|
||||
- 从媒体库、产品、文章和内部路由中选择引用。
|
||||
- 保存草稿。
|
||||
- 创建静态预览。
|
||||
- 显示字段和模板校验错误。
|
||||
|
||||
### 9.2 不在 V1 实现
|
||||
|
||||
- 画布上任意拖动位置。
|
||||
- 任意列宽和像素级布局。
|
||||
- 无限层级嵌套板块。
|
||||
- 管理员输入 CSS/JavaScript。
|
||||
- 在一个主题中自由调用另一个主题的组件。
|
||||
|
||||
---
|
||||
|
||||
## 10. Astro 渲染实现
|
||||
|
||||
### 10.1 渲染器注册
|
||||
|
||||
```ts
|
||||
import HeroBlock from '../blocks/HeroBlock.astro';
|
||||
import RichTextBlock from '../blocks/RichTextBlock.astro';
|
||||
import ProductGridBlock from '../blocks/ProductGridBlock.astro';
|
||||
|
||||
export const blockRenderers = {
|
||||
hero: HeroBlock,
|
||||
'rich-text': RichTextBlock,
|
||||
'product-grid': ProductGridBlock,
|
||||
} as const;
|
||||
```
|
||||
|
||||
### 10.2 页面循环
|
||||
|
||||
```astro
|
||||
---
|
||||
import { blockRenderers } from '../lib/block-renderers';
|
||||
|
||||
const { page } = Astro.props;
|
||||
const blocks = page.blocks.filter((block) => block.visibility.enabled);
|
||||
---
|
||||
|
||||
{blocks.map((block) => {
|
||||
const Renderer = blockRenderers[block.type];
|
||||
return Renderer
|
||||
? <Renderer block={block} page={page} />
|
||||
: null;
|
||||
})}
|
||||
```
|
||||
|
||||
实际构建前必须已经验证所有板块类型。生产构建发现未知板块时应失败,不能静默生成空白区域;后台预览可以显示“当前主题不支持该板块”的占位提示。
|
||||
|
||||
### 10.3 数据解析顺序
|
||||
|
||||
```text
|
||||
读取发布快照
|
||||
→ 获取页面与内容引用
|
||||
→ 获取模板定义
|
||||
→ 验证允许的板块和数量
|
||||
→ 按 schema 校验每个板块
|
||||
→ 解析媒体与内部链接
|
||||
→ 选择主题渲染器
|
||||
→ 生成 HTML
|
||||
→ 执行 SEO/链接/资源验收
|
||||
```
|
||||
|
||||
### 10.4 客户端 JavaScript
|
||||
|
||||
Astro 默认输出静态 HTML。只有轮播、菜单、筛选等确需交互的组件才使用客户端 hydration,并选择合适的加载策略。普通文本、产品参数和 FAQ 不应无条件加载完整前端框架。
|
||||
|
||||
---
|
||||
|
||||
## 11. 主题切换策略
|
||||
|
||||
### 11.1 可以直接切换的条件
|
||||
|
||||
- 新主题支持当前页面模板。
|
||||
- 新主题支持页面使用的全部板块类型。
|
||||
- 每个板块的 schema 版本兼容。
|
||||
- 主题所需站点配置完整。
|
||||
|
||||
### 11.2 切换前检查
|
||||
|
||||
系统先生成兼容报告:
|
||||
|
||||
```text
|
||||
支持的模板
|
||||
缺失的板块渲染器
|
||||
不支持的 variant
|
||||
缺失的站点配置
|
||||
需要迁移的数据版本
|
||||
```
|
||||
|
||||
存在不支持板块时,不允许直接用于生产构建。可以:
|
||||
|
||||
- 为新主题增加渲染器。
|
||||
- 将板块转换为兼容类型。
|
||||
- 由管理员明确删除或替换。
|
||||
|
||||
### 11.3 主题切换不是主要目标
|
||||
|
||||
平台需要支持主题版本升级和兼容检查,但不必把“任何网站一键换任意主题”作为 V1 目标。不同网站设计差异很大,强行互换会让板块协议变得臃肿。
|
||||
|
||||
---
|
||||
|
||||
## 12. 板块版本与数据迁移
|
||||
|
||||
板块必须携带 `schemaVersion`。
|
||||
|
||||
```ts
|
||||
type BlockMigration = {
|
||||
blockType: string;
|
||||
fromVersion: number;
|
||||
toVersion: number;
|
||||
migrate: (oldData: unknown) => unknown;
|
||||
};
|
||||
```
|
||||
|
||||
例如 Hero V2 将 `buttonText` 和 `buttonUrl` 合并为 `primaryAction`:
|
||||
|
||||
```text
|
||||
v1 data
|
||||
→ 运行纯函数迁移
|
||||
→ v2 data
|
||||
→ schema 校验
|
||||
→ 生成新的内容修订
|
||||
```
|
||||
|
||||
禁止直接批量覆盖已发布修订。迁移失败的板块进入人工处理列表,旧版本数据继续保留。
|
||||
|
||||
---
|
||||
|
||||
## 13. API 建议
|
||||
|
||||
```text
|
||||
GET /api/v1/themes
|
||||
GET /api/v1/themes/:themeId/manifest
|
||||
GET /api/v1/sites/:siteId/theme
|
||||
PUT /api/v1/sites/:siteId/theme
|
||||
|
||||
GET /api/v1/sites/:siteId/pages/:pageId/blocks
|
||||
POST /api/v1/sites/:siteId/pages/:pageId/blocks
|
||||
PATCH /api/v1/sites/:siteId/pages/:pageId/blocks/:blockId
|
||||
DELETE /api/v1/sites/:siteId/pages/:pageId/blocks/:blockId
|
||||
POST /api/v1/sites/:siteId/pages/:pageId/blocks/reorder
|
||||
POST /api/v1/sites/:siteId/pages/:pageId/validate
|
||||
POST /api/v1/sites/:siteId/pages/:pageId/preview
|
||||
|
||||
GET /api/v1/sites/:siteId/fragments
|
||||
POST /api/v1/sites/:siteId/fragments
|
||||
PATCH /api/v1/sites/:siteId/fragments/:fragmentId
|
||||
```
|
||||
|
||||
后端负责验证模板、板块类型、schema、variant、媒体和内部链接;不能只在管理后台进行校验。
|
||||
|
||||
---
|
||||
|
||||
## 14. 测试策略
|
||||
|
||||
### 14.1 契约测试
|
||||
|
||||
- 每个主题 manifest 格式正确。
|
||||
- 模板引用的板块都有渲染器。
|
||||
- 板块数据能通过对应 schema。
|
||||
- 主题声明的 variant 都能渲染。
|
||||
- 必需板块和最大数量约束有效。
|
||||
|
||||
### 14.2 渲染测试
|
||||
|
||||
- 每个模板至少有一份标准 fixture。
|
||||
- 每个板块测试最少字段、完整字段和异常字段。
|
||||
- 生成 HTML 不包含预览域名、危险脚本和无效资源。
|
||||
- 核心内容在输出 HTML 中真实存在,而非仅客户端加载。
|
||||
|
||||
### 14.3 视觉测试
|
||||
|
||||
- 为首页、产品详情、文章详情和普通页面生成桌面/移动截图。
|
||||
- 主题版本变化时对比关键页面。
|
||||
- 视觉差异由超级管理员确认后才能用于生产发布。
|
||||
|
||||
### 14.4 性能与可访问性
|
||||
|
||||
- 图片包含宽高并使用合适尺寸。
|
||||
- 交互组件按需加载。
|
||||
- 标题层级、链接、按钮和表单具有正确语义。
|
||||
- 颜色对比、键盘操作和焦点状态在主题验收中检查。
|
||||
|
||||
---
|
||||
|
||||
## 15. V1 实现顺序
|
||||
|
||||
### Sprint 1:契约和最小渲染
|
||||
|
||||
- 建立 `block-contracts`。
|
||||
- 建立 `ui-primitives`、`theme-runtime` 和 `content-resolvers` 的最小公共包。
|
||||
- 定义 Hero、Rich Text、Image Text、Gallery、CTA、FAQ 六个基础板块。
|
||||
- 建立主题 manifest 和模板协议。
|
||||
- 使用固定 JSON 生成一个静态首页。
|
||||
|
||||
### Sprint 2:数据库和后台编辑
|
||||
|
||||
- 建立 `page_blocks` 和内容修订。
|
||||
- 根据 schema 生成表单。
|
||||
- 支持新增、编辑、删除、排序和隐藏。
|
||||
- 支持媒体和内部链接选择。
|
||||
|
||||
### Sprint 3:主题与预览
|
||||
|
||||
- 完成第一套主题的首页、普通页面、产品详情和文章详情。
|
||||
- 建立预览构建。
|
||||
- 增加模板与板块兼容检查。
|
||||
|
||||
### Sprint 4:第二主题验证
|
||||
|
||||
- 使用相同基础板块数据开发视觉完全不同的第二主题。
|
||||
- 验证哪些字段真正通用,哪些需要站点专属板块。
|
||||
- 将两个主题中重复的非视觉逻辑提取到公共组件包。
|
||||
- 固化主题 SDK、测试 fixture 和开发文档。
|
||||
|
||||
### Sprint 5:生产质量
|
||||
|
||||
- 板块版本迁移。
|
||||
- 全局板块。
|
||||
- 视觉回归、可访问性和性能检查。
|
||||
- 与发布门禁和不可变 release 集成。
|
||||
|
||||
---
|
||||
|
||||
## 16. 首版基础板块清单
|
||||
|
||||
建议首版只实现以下 12 个,真实试点需要后再增加:
|
||||
|
||||
| 板块 | 核心字段 |
|
||||
|---|---|
|
||||
| Hero | eyebrow、title、description、media、actions |
|
||||
| Rich Text | content |
|
||||
| Image Text | title、content、media、mediaPosition、action |
|
||||
| Gallery | title、items |
|
||||
| Feature List | title、items、icon/media |
|
||||
| Statistics | title、items(value/label) |
|
||||
| Product Grid | title、productRefs/query、limit、action |
|
||||
| Article List | title、category/query、limit、action |
|
||||
| Specification Table | title、groups/rows 或 product field binding |
|
||||
| Download List | title、assetRefs |
|
||||
| FAQ | title、items(question/answer) |
|
||||
| CTA | title、description、media、actions |
|
||||
|
||||
Header、Footer、Breadcrumb、产品主信息和文章主内容作为全局/模板系统组件单独实现,不计入可自由添加板块。
|
||||
|
||||
---
|
||||
|
||||
## 17. 开发验收标准
|
||||
|
||||
主题与板块模块达到以下条件即可视为 V1 完成:
|
||||
|
||||
1. 超级管理员能为页面选择模板。
|
||||
2. 能新增、编辑、排序、隐藏和删除模板允许的板块。
|
||||
3. 后台字段由 schema 驱动,并在前后端双重验证。
|
||||
4. 相同板块数据能被两套主题渲染成明显不同的设计。
|
||||
5. 主题不支持某板块时,生产构建会被阻止并给出明确错误。
|
||||
6. 产品详情和文章详情能混合系统板块与可配置板块。
|
||||
7. 全局 Header/Footer 修改后能够重新构建站点。
|
||||
8. 所有发布版本锁定主题版本和板块修订,可准确回滚。
|
||||
9. 页面输出为静态 HTML,核心内容无需 JavaScript 即可读取。
|
||||
10. 主题和板块变更进入现有 URL、SEO、内容和视觉发布门禁。
|
||||
11. 两套主题复用相同的数据契约、媒体、SEO 和 Headless 逻辑,但最终页面视觉明显不同。
|
||||
|
||||
---
|
||||
|
||||
## 18. 最终建议
|
||||
|
||||
首版主题系统的重点不是“让管理员设计网页”,而是让开发者能够快速制作不同主题,让管理员安全地维护结构化内容。
|
||||
|
||||
必须守住三个边界:
|
||||
|
||||
1. 内容数据中不写 CSS 和组件路径。
|
||||
2. 主题不能自己决定历史 URL 和 SEO。
|
||||
3. 未知或不兼容板块不能在生产构建中静默消失。
|
||||
|
||||
按“统一协议、独立渲染、有限配置、严格校验”实现,既能保留每个网站的设计自由度,也能让后续内容维护和新站迁移真正复用同一套系统。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,552 @@
|
||||
# SiteForge 现有 CMS 项目复用评估 V1.0
|
||||
|
||||
> 评估对象:`D:\project\cms`
|
||||
> 目标项目:`D:\project\cms-one`(SiteForge)
|
||||
> 评估日期:2026-10-20
|
||||
> 依据:现有源码、数据库 Schema、测试、构建脚本、基础设施配置,以及 SiteForge V3.0 方案与实施计划。
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论
|
||||
|
||||
`D:\project\cms` 不是简单样例,而是一个已经具备管理后台、控制 API、WordPress 迁移、内容模型、Astro 静态站运行时和基础测试的早期平台原型。
|
||||
|
||||
它与 SiteForge 的目标高度同源,适合作为**代码底座和经验来源**,不建议把 SiteForge 完全从零重写。但它当前仍然是“单站 MVP 向平台化演进”的状态,部分文档设计明显领先于实际代码,因此不能整体原样搬入。
|
||||
|
||||
推荐原则:
|
||||
|
||||
1. SiteForge V3.0 方案继续作为当前项目的唯一产品与架构基线。
|
||||
2. 选择性继承 `cms` 中已经验证的代码,不继承其过时的权限、发布、路由和数据边界。
|
||||
3. 优先复用迁移解析、内容版本、管理后台壳、Astro 组件、测试夹具等高价值资产。
|
||||
4. 对认证、发布、路由注册、主题架构、媒体安全和表单服务进行结构性重构。
|
||||
5. 不复制缓存、依赖目录、构建产物、真实客户数据和历史存储文件。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前项目可以直接参考或复用的部分
|
||||
|
||||
### 2.1 Monorepo 工程骨架
|
||||
|
||||
来源:
|
||||
|
||||
- `D:\project\cms\package.json`
|
||||
- `D:\project\cms\pnpm-workspace.yaml`
|
||||
- `D:\project\cms\turbo.json`
|
||||
- `D:\project\cms\.github\workflows`
|
||||
|
||||
可复用内容:
|
||||
|
||||
- pnpm Workspace + Turborepo 的项目组织方式。
|
||||
- 管理后台、控制 API、构建 Worker、站点运行时和公共包的目录边界。
|
||||
- TypeScript、Vitest、CI 的基础配置。
|
||||
- 统一执行 `typecheck`、`test`、`build` 的任务编排。
|
||||
|
||||
需要调整:
|
||||
|
||||
- CI 安装应使用冻结锁文件,而不是 `--no-frozen-lockfile`。
|
||||
- 增加数据库迁移校验、OpenAPI 契约校验、静态站质量门禁、安全扫描和产物校验。
|
||||
- 不复制 `node_modules`、`.turbo`、`.data`、本地日志和构建输出。
|
||||
|
||||
复用等级:**高,可以直接作为工程骨架参考。**
|
||||
|
||||
### 2.2 Art Design Pro 管理后台基础
|
||||
|
||||
来源:`D:\project\cms\apps\admin-web`
|
||||
|
||||
已有能力:
|
||||
|
||||
- Vue 3 + TypeScript + Element Plus。
|
||||
- Art Design Pro 布局、菜单、路由、Pinia、Axios 和通用组件。
|
||||
- 站点列表、站点管理、内容管理、媒体、导航、设置、线索和迁移页面。
|
||||
- WordPress 迁移的步骤式界面。
|
||||
|
||||
建议保留:
|
||||
|
||||
- 登录后主布局、导航、标签页、请求封装、异常处理和基础表格表单组件。
|
||||
- 站点切换、站点列表、迁移向导和媒体选择器的交互结构。
|
||||
- Element Plus 设计体系以及 Art Design Pro 已有的工程规范。
|
||||
|
||||
必须精简:
|
||||
|
||||
- 删除注册、找回密码、动态权限演示和多角色菜单逻辑。
|
||||
- 用户角色只保留一个全局 `super_admin`,不设计复杂 RBAC。
|
||||
- 清理仪表盘、电商演示、Mock 页面和无关组件。
|
||||
- 将体积过大的站点管理页面拆成独立领域页面和复用组件。
|
||||
- 内容表单由硬编码逐步改为 Schema 驱动。
|
||||
- 复用前确认 Art Design Pro 及第三方资源的许可证适用范围。
|
||||
|
||||
复用等级:**高,建议直接继承后台壳和通用能力,业务页面按新方案重构。**
|
||||
|
||||
### 2.3 NestJS + Fastify + Drizzle 后端基础
|
||||
|
||||
来源:`D:\project\cms\services\control-api`
|
||||
|
||||
已有模块:
|
||||
|
||||
- 认证。
|
||||
- 站点管理。
|
||||
- 内容类型、内容条目和内容版本。
|
||||
- 媒体管理。
|
||||
- WordPress 迁移。
|
||||
- 线索管理。
|
||||
- 构建触发。
|
||||
|
||||
可复用内容:
|
||||
|
||||
- NestJS 模块化结构和 Fastify 适配。
|
||||
- Drizzle + PostgreSQL 的访问方式。
|
||||
- Zod 输入校验思路。
|
||||
- 显式 `site_id` 上下文和站点隔离测试。
|
||||
- 内容版本不可变、草稿与发布版本分离的基础设计。
|
||||
- 站点模板初始化和默认导航生成逻辑。
|
||||
|
||||
需要重构:
|
||||
|
||||
- 用户表当前为站点级并带历史角色字段,应改为平台级单超管模型。
|
||||
- 自制 HMAC Token 缺少成熟的过期、刷新、撤销和 MFA 机制,应替换。
|
||||
- 审计日志、发布记录、构建任务和路由记录需要成为正式数据表,而不是内存或 JSON 附属数据。
|
||||
- API 应补齐 OpenAPI、统一错误码、幂等键、操作审计和敏感操作二次确认。
|
||||
|
||||
复用等级:**高,适合作为后端起点,但认证和发布领域不可原样沿用。**
|
||||
|
||||
### 2.4 WordPress REST/WXR 迁移能力
|
||||
|
||||
来源:
|
||||
|
||||
- `D:\project\cms\services\control-api\src\migration`
|
||||
- `D:\project\cms\apps\admin-web\src\views\sites\migrate-tab.vue`
|
||||
- `D:\project\cms\tests`
|
||||
|
||||
已有能力:
|
||||
|
||||
- WordPress REST API 拉取。
|
||||
- WXR 文件解析。
|
||||
- 文章、产品等内容转换为中间结构。
|
||||
- 媒体下载、去重和关联。
|
||||
- 类型映射、迁移预览、批次导入和结果报告。
|
||||
- 基于旧地址生成部分重定向。
|
||||
- 幂等迁移和相关端到端测试。
|
||||
|
||||
这是旧项目中最值得保留的资产之一。现有文档还记录了多个真实网站迁移规模,说明相关代码不是纯概念设计。
|
||||
|
||||
必须调整:
|
||||
|
||||
- 迁移后不能自动发布,必须进入“导入批次 → 校验 → 人工审核 → 预览 → 发布”的流程。
|
||||
- 旧 URL 不能只保存在 `siteSettings` JSON 中,应写入正式的 `route_registry`。
|
||||
- 页面、分类、标签、自定义文章类型、附件和 SEO 元数据需要统一映射策略。
|
||||
- 不能把无法映射的旧页面一律跳转首页,应进入冲突清单并人工处理。
|
||||
- 语言不能硬编码为 `en/es`,应使用站点 Locale 配置。
|
||||
- 增加断点续传、失败重试、限流、增量迁移、差异报告和可回滚批次。
|
||||
- 从 HTML 提取内容时增加 XSS 清理和资源地址标准化。
|
||||
|
||||
复用等级:**很高,保留解析器、UniversalRow 思路、媒体抓取和测试夹具,重做迁移编排。**
|
||||
|
||||
### 2.5 内容模型、版本与导入幂等
|
||||
|
||||
来源:
|
||||
|
||||
- `D:\project\cms\services\control-api\src\content`
|
||||
- `D:\project\cms\services\control-api\src\db`
|
||||
- `D:\project\cms\docs\contracts\导入模板V1.md`
|
||||
|
||||
可复用内容:
|
||||
|
||||
- 内容类型定义与内容条目分离。
|
||||
- 多语言内容记录。
|
||||
- 不可变版本记录。
|
||||
- 通过 `externalRef`、Slug 等键进行幂等合并。
|
||||
- 导入预校验、错误报告、状态机和 CSV 安全方面的设计经验。
|
||||
|
||||
建议作为 SiteForge 内容中台的起点,但需要补充:
|
||||
|
||||
- 内容发布状态机。
|
||||
- 计划发布和撤回。
|
||||
- 关联内容完整性。
|
||||
- Slug/URL 冲突检测。
|
||||
- 导入批次与每条记录的来源追踪。
|
||||
- 批次级回滚。
|
||||
- 删除保护和引用检查。
|
||||
|
||||
复用等级:**高。**
|
||||
|
||||
### 2.6 Astro 静态站运行时和页面质量门禁
|
||||
|
||||
来源:`D:\project\cms\runtimes\astro-site-runtime`
|
||||
|
||||
已有能力:
|
||||
|
||||
- Astro 5 静态站构建。
|
||||
- 首页、产品、分类、新闻、项目、关于、联系、支持和 Sitemap 页面。
|
||||
- Header、Footer、Hero、分页、表单、卡片网格、CTA 等组件。
|
||||
- 基础主题 Token。
|
||||
- Title、Description、Canonical、H1、内部链接、图片和 Sitemap 检查。
|
||||
- 重定向文件生成。
|
||||
- 版本化构建产物和基础回滚脚本。
|
||||
|
||||
可直接复用:
|
||||
|
||||
- Astro 的构建基础。
|
||||
- 现有语义组件和样式 Token 的代码经验。
|
||||
- 门禁脚本和重定向生成器作为第一版基础。
|
||||
- SEO 页面输出和 Sitemap 生成思路。
|
||||
|
||||
必须重构:
|
||||
|
||||
- 页面不能继续依赖硬编码站点配置和默认内容。
|
||||
- 编译器必须读取冻结的发布快照,而不是构建过程中读取变化中的在线数据。
|
||||
- 主题应拆成主题包、主题清单、Token、布局、区块注册表和站点配置。
|
||||
- 区块应由统一 Block Renderer 渲染,不能每个网站复制页面文件。
|
||||
- 构建产物切换要使用真正的原子发布机制,而不是删除后复制。
|
||||
- 门禁检查应使用 HTML 解析器而不是仅靠正则,并增加重复元数据、结构化数据、hreflang、孤链、重定向环、状态码和性能预算。
|
||||
|
||||
复用等级:**中高,适合作为静态运行时原型,不应直接作为最终主题架构。**
|
||||
|
||||
### 2.7 主题 Token 和组件契约文档
|
||||
|
||||
来源:
|
||||
|
||||
- `D:\project\cms\docs\contracts\ThemeToken契约V1.md`
|
||||
- `D:\project\cms\docs\contracts\组件契约V1.md`
|
||||
|
||||
值得吸收的内容:
|
||||
|
||||
- 使用语义 Token,而不是在组件中直接写颜色和尺寸。
|
||||
- 主题变体、版本号和升级迁移规则。
|
||||
- 组件输入、插槽、SEO、可访问性和懒加载约束。
|
||||
- Hero、CardGrid、FeatureGrid、CTA 等组件的标准化思路。
|
||||
- WCAG 2.2 AA 作为可访问性目标。
|
||||
|
||||
与 SiteForge 的结合方式:
|
||||
|
||||
- 把“组件契约”升级为正式的 Block Manifest。
|
||||
- 每个组件声明字段 Schema、默认值、允许的布局、SEO 行为、资源依赖和兼容版本。
|
||||
- 区分基础 UI 组件、内容区块、页面模板和站点主题四个层级。
|
||||
- 主题只能组合和覆盖,不得复制修改公共组件源码。
|
||||
|
||||
复用等级:**高,适合作为当前主题与组件规范的补充输入。**
|
||||
|
||||
### 2.8 PostgreSQL、Redis、MinIO 基础设施
|
||||
|
||||
来源:`D:\project\cms\infrastructure`
|
||||
|
||||
建议沿用:
|
||||
|
||||
- PostgreSQL:业务数据库。
|
||||
- Redis:队列、分布式锁、缓存和限流。
|
||||
- MinIO:本地开发的 S3 兼容对象存储。
|
||||
|
||||
需要修改:
|
||||
|
||||
- 生产环境使用受控对象存储或独立部署的兼容服务。
|
||||
- 镜像必须固定版本,不能长期使用 `latest`。
|
||||
- 开发密码不得用于生产。
|
||||
- 增加备份、恢复演练、生命周期、跨环境配置和 Secret 管理。
|
||||
|
||||
复用等级:**高。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 可以参考,但必须重构后使用的部分
|
||||
|
||||
### 3.1 认证与权限
|
||||
|
||||
旧项目保留了多角色和站点级用户的历史痕迹,而 SiteForge 已明确只需要一个超级管理员。
|
||||
|
||||
新设计应为:
|
||||
|
||||
- 平台只有一个 `super_admin` 权限模型。
|
||||
- 可允许配置一个或少量超级管理员账号,但权限完全一致,不建立角色矩阵。
|
||||
- 使用成熟密码哈希、短期访问凭证、刷新/撤销机制、MFA、登录限流和安全日志。
|
||||
- 所有高风险操作记录操作者、站点、对象、前后差异、IP、User-Agent 和时间。
|
||||
|
||||
旧认证代码只能参考接口结构,不能作为生产安全方案直接使用。
|
||||
|
||||
### 3.2 构建、发布与回滚
|
||||
|
||||
旧项目当前主要问题:
|
||||
|
||||
- 构建记录保存在进程内存中。
|
||||
- API 进程直接启动构建命令。
|
||||
- 构建锁仅在单进程内有效。
|
||||
- Build Worker 目录基本还是占位。
|
||||
- 发布替换并非严格原子操作。
|
||||
- 回滚没有完整持久化的 Release 记录。
|
||||
|
||||
SiteForge 应改为:
|
||||
|
||||
1. API 创建持久化 Build Job。
|
||||
2. Redis/BullMQ Worker 异步消费。
|
||||
3. 同站点使用分布式发布锁。
|
||||
4. 构建读取不可变 Site Snapshot。
|
||||
5. 产物写入版本目录或对象存储。
|
||||
6. 门禁通过后原子切换当前 Release 指针。
|
||||
7. 每次发布记录输入快照、代码版本、主题版本、产物校验和和日志。
|
||||
8. 回滚只切换到已验证 Release,不重新现场构建。
|
||||
|
||||
可继承的是构建命令、Astro 产物组织和基础门禁;发布编排需要重做。
|
||||
|
||||
### 3.3 路由与 SEO
|
||||
|
||||
旧项目能生成重定向文件,但路由仍是附属设置,不足以支撑“原路径不变”的核心要求。
|
||||
|
||||
SiteForge 必须建立独立的 `route_registry`:
|
||||
|
||||
- 每条公开 URL 都有唯一注册记录。
|
||||
- 保存站点、Locale、路径、资源类型、资源 ID、状态、Canonical 和历史来源。
|
||||
- 写入内容时先预占或校验路由。
|
||||
- 迁移前导入完整旧站 URL 清单。
|
||||
- 构建时从注册表生成页面和重定向。
|
||||
- 发布门禁对旧 URL 覆盖率、404、重定向环和多跳重定向进行检查。
|
||||
|
||||
旧项目的 Redirect 生成脚本可以保留,但数据源应切换到路由注册表。
|
||||
|
||||
### 3.4 媒体系统
|
||||
|
||||
旧媒体模块已有 Sharp 缩略图和来源 URL 去重,可以保留处理经验,但存在以下缺口:
|
||||
|
||||
- 主要依赖本地磁盘。
|
||||
- SVG 缺少严格清理。
|
||||
- 删除时缺少完整引用检查。
|
||||
- 未形成原文件、变体、Hash、使用关系和删除状态的完整模型。
|
||||
|
||||
SiteForge 应实现:
|
||||
|
||||
- S3 兼容对象存储。
|
||||
- 文件 Hash 去重和 MIME 魔数校验。
|
||||
- SVG 清理或默认禁用上传。
|
||||
- 图片尺寸、格式、焦点、Alt 和变体管理。
|
||||
- `media_usage` 引用关系。
|
||||
- 软删除、延迟物理删除和可恢复窗口。
|
||||
- WebP/AVIF 等派生资源异步生成。
|
||||
|
||||
### 3.5 表单与线索
|
||||
|
||||
旧 Lead 模块只适合作为简单 CRUD 示例,尚不等于可对公网开放的 Form API。
|
||||
|
||||
SiteForge 应补充:
|
||||
|
||||
- 表单定义和字段 Schema。
|
||||
- 来源页面、UTM、Referrer、站点和 Locale。
|
||||
- 服务端校验、蜜罐、验证码、频率限制和重复提交保护。
|
||||
- 隐私同意记录和可配置保留期限。
|
||||
- 通知重试、Webhook 签名和失败队列。
|
||||
- CSV 导出安全处理。
|
||||
- 所有更新必须同时按 `site_id` 和记录 ID 定位。
|
||||
|
||||
### 3.6 站点主题与页面编辑
|
||||
|
||||
旧运行时已有 Token 和组件,但页面结构仍偏硬编码。SiteForge 应建立四层结构:
|
||||
|
||||
1. **基础组件层**:Button、Container、Image、RichText 等。
|
||||
2. **业务区块层**:Hero、ProductGrid、NewsList、FAQ、CTA、ContactForm 等。
|
||||
3. **页面模板层**:首页、产品列表、产品详情、新闻列表、文章详情和普通页面。
|
||||
4. **主题层**:Token、字体、间距、装饰样式、默认区块组合和可用模板清单。
|
||||
|
||||
主题包至少包含:
|
||||
|
||||
- `theme.manifest.ts`
|
||||
- `tokens.ts`
|
||||
- `blocks/`
|
||||
- `layouts/`
|
||||
- `templates/`
|
||||
- `styles/`
|
||||
- `migrations/`
|
||||
|
||||
后台编辑的是结构化区块配置,前台由 Block Renderer 统一渲染。这样才能同时做到不同网站效果不同、组件可复用、数据可迁移和主题可升级。
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前阶段不建议复用或应暂缓的部分
|
||||
|
||||
### 4.1 数据分析和客户身份体系
|
||||
|
||||
旧文档中包含事件网关、ClickHouse、Tracking Plan、客户画像和增长分析等设计。这些能力会显著增加系统复杂度,但不是 SiteForge 第一阶段完成网站迁移、发布和维护的必要条件。
|
||||
|
||||
建议:
|
||||
|
||||
- V1 只保留基础访问统计接入位和必要操作日志。
|
||||
- Event Gateway、ClickHouse、统一客户身份和高级分析延后到独立阶段。
|
||||
|
||||
### 4.2 复杂 RBAC、多租户商业化和计费
|
||||
|
||||
当前需求已经明确只需超级管理员,因此暂不建设:
|
||||
|
||||
- 角色与权限矩阵。
|
||||
- 团队邀请和成员管理。
|
||||
- 租户套餐、用量计费和支付。
|
||||
- 审批流。
|
||||
|
||||
数据库可保留未来扩展空间,但不应为了可能的需求增加当前实现负担。
|
||||
|
||||
### 4.3 旧项目的真实数据与运行目录
|
||||
|
||||
不得直接复制:
|
||||
|
||||
- `.data`
|
||||
- `storage`
|
||||
- `node_modules`
|
||||
- `.turbo`
|
||||
- `.playwright-mcp`
|
||||
- 构建产物和运行日志
|
||||
- 客户网站内容、媒体、线索和导入文件
|
||||
- `.env`、Token、密码及其他 Secret
|
||||
|
||||
确需使用真实迁移样本时,应先获得授权并完成脱敏,再转换为最小测试夹具。
|
||||
|
||||
### 4.4 历史文档的权威地位
|
||||
|
||||
旧项目文档中有大量值得借鉴的设计,但部分功能只存在于文档,代码尚未实现;也有部分规则与 SiteForge 当前单超管、统一路由和冻结快照发布模型冲突。
|
||||
|
||||
因此:
|
||||
|
||||
- SiteForge V3.0 方案是当前项目的权威基线。
|
||||
- 旧项目文档仅作为输入和参考。
|
||||
- 任何旧设计进入实现前,都要映射到 SiteForge 的领域模型和验收标准。
|
||||
|
||||
---
|
||||
|
||||
## 5. 复用优先级矩阵
|
||||
|
||||
| 能力 | 现状 | 复用建议 | 优先级 |
|
||||
|---|---|---|---|
|
||||
| pnpm/Turborepo 工程骨架 | 已成型 | 直接参考/继承 | P0 |
|
||||
| Art Design Pro 后台壳 | 已成型 | 保留壳,清理演示与多角色 | P0 |
|
||||
| NestJS/Fastify/Drizzle | 已成型 | 作为 API 基础 | P0 |
|
||||
| 站点上下文与隔离测试 | 已有实现 | 保留并扩大覆盖 | P0 |
|
||||
| WordPress REST/WXR 解析 | 已有实现和测试 | 重点继承,重做迁移流程 | P0 |
|
||||
| 内容类型和版本 | 基本可用 | 扩展状态机与发布模型 | P0 |
|
||||
| Astro 静态运行时 | 原型可用 | 保留构建基础,重构主题架构 | P0 |
|
||||
| 主题 Token/组件契约 | 文档较完整 | 纳入新主题规范 | P0 |
|
||||
| Redirect 生成 | 已有脚本 | 改用 route_registry 数据源 | P0 |
|
||||
| SEO Gate | 基础版本 | 保留并增强 | P0 |
|
||||
| PostgreSQL/Redis/MinIO | 已配置 | 直接沿用技术选型 | P0 |
|
||||
| 导入幂等和报告 | 有基础 | 扩展为批次、回滚、差异报告 | P1 |
|
||||
| 媒体缩略图处理 | 有基础 | 保留 Sharp,重构存储与安全 | P1 |
|
||||
| 站点模板初始化 | 有基础 | 改造成站点蓝图/主题初始化 | P1 |
|
||||
| Lead CRUD | 简单实现 | 仅参考,重做公网 Form API | P1 |
|
||||
| BuildService | 原型 | 不直接复用,改为队列 Worker | P1 |
|
||||
| Event Gateway | 占位/早期 | 暂缓 | P3 |
|
||||
| ClickHouse/增长分析 | 超出当前范围 | 暂缓 | P3 |
|
||||
| 多角色 RBAC | 与需求冲突 | 不采用 | 不做 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 推荐落地方式
|
||||
|
||||
### 方案 A:以旧项目代码为技术底座进行净化和重构(推荐)
|
||||
|
||||
做法:
|
||||
|
||||
- 保留旧项目 Git 历史或创建一条新的 SiteForge 开发分支/仓库。
|
||||
- 删除缓存、数据、演示页面和超出范围的模块。
|
||||
- 以 SiteForge V3.0 的数据模型、模块边界和实施计划逐步替换旧实现。
|
||||
- 每完成一个领域,就补齐迁移脚本、测试和验收门禁。
|
||||
|
||||
优点:
|
||||
|
||||
- 最大化利用已经写好的管理后台、迁移解析器、API 和 Astro 代码。
|
||||
- 保留真实问题的修复经验和测试用例。
|
||||
- 比从空目录重建更快进入可运行状态。
|
||||
|
||||
风险:
|
||||
|
||||
- 必须主动偿还旧原型留下的结构债务。
|
||||
- 不能为了短期速度保留内存发布、JSON 路由、自制 Token 等关键缺陷。
|
||||
|
||||
### 方案 B:保持 `cms-one` 为全新仓库,选择性移植源码
|
||||
|
||||
适用于希望彻底清理历史包袱的情况。
|
||||
|
||||
建议只移植:
|
||||
|
||||
- 后台通用壳和基础组件。
|
||||
- WordPress/WXR 解析器与测试夹具。
|
||||
- 内容版本、幂等导入的核心逻辑。
|
||||
- Astro 通用组件、主题 Token 和门禁脚本。
|
||||
- PostgreSQL/Redis/MinIO 开发环境配置。
|
||||
|
||||
不要整目录复制。每次移植都应有对应的模块边界、测试和依赖清单。
|
||||
|
||||
综合成本与风险,推荐采用**方案 A 的代码继承方式 + 方案 B 的选择性净化原则**:把旧项目当成可运行底座,但按 SiteForge 方案逐域重构,而不是延续旧项目产品定义。
|
||||
|
||||
---
|
||||
|
||||
## 7. 第一批实际迁移任务
|
||||
|
||||
### 第 1 批:建立干净基线
|
||||
|
||||
1. 确认源码许可证和第三方资产许可证。
|
||||
2. 导出仅包含受版本控制源码的干净代码副本。
|
||||
3. 排除数据、媒体、日志、缓存、依赖和 Secret。
|
||||
4. 删除后台演示页面、多角色路由和无关分析模块。
|
||||
5. 固化 Node、pnpm、PostgreSQL、Redis 和 MinIO 版本。
|
||||
6. 跑通 lint、typecheck、unit、e2e 和静态站构建基线。
|
||||
|
||||
### 第 2 批:修正核心架构
|
||||
|
||||
1. 实现平台级单超级管理员认证。
|
||||
2. 建立 `route_registry`、`import_batches`、`build_jobs`、`releases`、`publish_locks` 等核心表。
|
||||
3. 将构建改为持久化队列 Worker。
|
||||
4. 将静态站编译输入改为冻结 Site Snapshot。
|
||||
5. 建立对象存储媒体模型和引用关系。
|
||||
|
||||
### 第 3 批:迁移与主题平台化
|
||||
|
||||
1. 把现有 WordPress REST/WXR 代码接入导入批次。
|
||||
2. 建立全量 URL 清单、映射、冲突和覆盖率报告。
|
||||
3. 将现有 Astro 组件整理为基础组件和业务区块。
|
||||
4. 实现 Theme Manifest、Block Manifest 和 Block Renderer。
|
||||
5. 完成第一个真实站点的迁移、预览、门禁和原子发布。
|
||||
|
||||
### 第 4 批:运营能力
|
||||
|
||||
1. Schema 驱动内容表单。
|
||||
2. 产品、新闻、普通页面和导航维护。
|
||||
3. 安全的公网 Form API 和线索后台。
|
||||
4. 发布历史、差异查看、一键回滚和审计日志。
|
||||
5. 备份恢复、监控告警和灾难恢复演练。
|
||||
|
||||
---
|
||||
|
||||
## 8. 需要优先修复的已发现风险
|
||||
|
||||
1. **发布记录在内存中**:服务重启会丢失构建历史和锁状态。
|
||||
2. **API 进程直接构建**:资源隔离、并发、重试和故障恢复不足。
|
||||
3. **迁移即发布**:不满足人工审核、预览和可回滚要求。
|
||||
4. **路由保存在 JSON 设置中**:无法可靠保证所有旧路径不变。
|
||||
5. **自制 Token 能力不足**:缺少完整过期、撤销、MFA 和会话管理。
|
||||
6. **本地媒体存储和直接删除**:生产可靠性和引用安全不足。
|
||||
7. **SVG 缺少清理**:存在持久化 XSS 风险。
|
||||
8. **Lead 更新条件不完整**:部分操作需同时限定 `site_id`。
|
||||
9. **页面和 Locale 存在硬编码**:无法稳定支持不同站点和语言组合。
|
||||
10. **文档数据库模型多于实际 Schema**:必须以迁移文件和运行代码确认真实能力。
|
||||
11. **正则式 HTML Gate 有边界缺陷**:需要 DOM 解析和浏览器级补充验证。
|
||||
12. **所谓原子发布仍有删除后复制窗口**:生产切换需要重新设计。
|
||||
|
||||
---
|
||||
|
||||
## 9. 最终建议
|
||||
|
||||
当前 SiteForge 项目应把 `D:\project\cms` 定位为:
|
||||
|
||||
- **实现底座**:复用工程骨架、后台壳、API 基础、迁移解析和 Astro 运行时。
|
||||
- **经验库**:复用真实迁移中沉淀的测试、映射和质量门禁经验。
|
||||
- **非权威需求来源**:产品范围、权限、发布和主题架构以 SiteForge V3.0 为准。
|
||||
|
||||
预计最能节省工期的五项资产是:
|
||||
|
||||
1. WordPress REST/WXR 迁移解析和测试。
|
||||
2. Art Design Pro 管理后台基础。
|
||||
3. NestJS/Fastify/Drizzle 内容 API 基础。
|
||||
4. Astro 静态站组件与 SEO Gate。
|
||||
5. 内容版本、幂等导入和站点隔离测试。
|
||||
|
||||
预计最不能直接继承的五项是:
|
||||
|
||||
1. 当前认证与多角色模型。
|
||||
2. 内存式构建和发布流程。
|
||||
3. JSON 化重定向与非正式路由管理。
|
||||
4. 本地媒体删除和安全策略。
|
||||
5. 迁移完成后直接发布的工作流。
|
||||
|
||||
按这个边界执行,可以保留旧项目的大部分有效研发投入,同时避免把原型阶段的关键技术债带入 SiteForge 的正式版本。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
# cms 代码库现状 vs SiteForge V3.0 差距分析与改造清单
|
||||
|
||||
> ⚠️ **本文档已作废(2026-10-20)**:被 `cms现状与SiteForge差距分析_V2.0.md` 取代。V2.0 修正了本文多处评级(隔离残留、非原子发布、SVG/媒体安全、迁移自动发布等,均以代码证据为准)。本文仅作历史参考,请勿据此决策。
|
||||
|
||||
> 版本:V1.0|日期:2026-10-20
|
||||
> 方法:SiteForge V3.0 §2.1 的 17 项必须交付能力为标尺,逐条对照 `D:\project\cms` 的**实际代码**(非文档声称),证据来自代码探索 + 迁移台账 + 契约文档。
|
||||
> 结论用途:走「C 路线」——以 cms 为基座继续演进,把 V3.0 当架构检查清单逐项吸收。
|
||||
|
||||
---
|
||||
|
||||
## 1. 总评
|
||||
|
||||
**17 项能力:已有 4 项、部分 9 项、缺失 4 项。**
|
||||
|
||||
cms 已经用真实数据(两站:hesupipe.com ✅ 完成、magicbridgeauto.com ⏸ 暂停)验证了最难的「迁移 → 静态构建 → 门禁 → 回滚」主干链路,这与 V3.0 的核心路径完全同构。缺口集中在:**部署上线(阻塞)、主题系统(平台化核心)、迁移质量增强(差量/冲突/URL 注册表)、账号与运维硬化**。
|
||||
|
||||
一句话:**V3.0 里"值钱的架构思想"cms 已吸收了一半(不可变修订、版本化产物、门禁、幂等),另一半(输入快照、URL 注册表、主题协议、部署器)就是改造清单的主线。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 十七项能力逐条对照
|
||||
|
||||
图例:✅ 已有(实战验证)|🟡 部分(能跑但有明显缺口)|❌ 缺失
|
||||
|
||||
| # | V3.0 必须交付 | 评级 | cms 实际现状(代码证据) | 关键差距 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 多站点与环境管理 | 🟡 | sites/域名/设置齐全;站点隔离已修复并有 e2e(`isolation.e2e.test.ts`,文档里的"X-Site-Id 未生效"是过时信息) | 无 staging/production 环境抽象;构建历史存内存(重启即丢) |
|
||||
| 2 | 单一超级管理员(MFA/恢复/会话撤销) | 🟡 | 登录 + bcrypt + 审计日志可用;单账号种子 | 自研 HMAC token **无过期、无撤销**;无 MFA/恢复码/登录限流;**登录页预填了默认账号密码** |
|
||||
| 3 | WordPress REST/WXR/SQL/uploads 导入 | ✅ | REST + WXR 双通道 + zip 媒体 sourceUrl 预入库 + externalRef 幂等 + WAF 退避;两站实战(33MB WXR 也解析了) | 缺 SQL 直连通道(第三通道);ACF 字段发现未做 |
|
||||
| 4 | Sitemap/HTML/Playwright 扫描 | ❌ | 仅拉取老站 sitemap.xml(1 级 index 递归) | 无 HTML 链接发现爬虫、无 Playwright;V3.0 的十来源 URL 全集完全没有 |
|
||||
| 5 | 原始快照与差量同步 | 🟡 | WXR 原件留档 storage/wxr;重跑幂等更新 | **无冲突队列、无人工编辑保护**(重跑无条件整条覆盖 data)、无新增/更新/删除/冲突的差量分类报告 |
|
||||
| 6 | 统一内容与内容修订 | ✅ | content_revisions 不可变(插入式)、公开端点只读 published 修订、5 种内容类型带 Schema | 缺乐观锁(last-write-wins,多标签页会互相覆盖);archived 状态无入口 |
|
||||
| 7 | URL 注册表与路由编译 | 🟡 | 301 存 site_settings.redirects(JSONB);三格式产物(_redirects/nginx conf/csv);三色报告 🔴missing=0 实战达标 | 无独立路由注册表(normalized key/route_kind/indexable);无 410/查询参数路由;无部署能力预检 |
|
||||
| 8 | SEO 快照与差异报告 | 🟡 | 出站 SEO 全套(title/desc/canonical/hreflang/og/twitter/noindex)+ Yoast 随迁 + 门禁查 title/H1/canonical + sitemap 一致性 | 无"旧站真实 HTML vs 新站"三套数据对比;无 P0–P3 分级差异报告 |
|
||||
| 9 | 媒体迁移与旧路径保持 | ✅ | 全量转存 + sourceUrl 幂等去重 + alt + 多尺寸;两站 5494 张实战、替换零残留 | 老站已被外链引用的媒体旧 URL 是否 301 未处理(对齐 V3.0"旧路径保持") |
|
||||
| 10 | 主题/模板/板块协议 | ❌ | templates 表存在但**空表无种子**;主题 Tab 能编辑 token 但**运行时没人消费(死线)**;后台表单全部硬编码;建站只有 1 个硬编码模板选项 | **最大缺口**(平台化文档自己标注)。ERD 里的 block_instances/template_slots/component_versions 设计未落地 |
|
||||
| 11 | 组件化公共包 | 🟡 | astro runtime 内共享数据源 + base 组件 + 183 个设计 token(契约测试保护);domain-contracts 类型包 | 无四层复用分层、无多主题目录结构(themes/)、无跨主题复用验证 |
|
||||
| 12 | Astro 全量静态构建 | ✅ | 版本化产物(.artifacts/,KEEP=10)+ 4 阶段原子发布 + 门禁 + 回滚(可再滚回) | **缺构建输入快照**:构建时实时拉 API,失败时**静默回落 seed 演示数据**(高危!) |
|
||||
| 13 | 预览、验收、发布、回滚 | 🟡 | 验收(gate.mjs)/发布/回滚完整且实战 | **草稿预览缺失**(只能发布后看);无生产冒烟 |
|
||||
| 14 | Nginx/SSH 发布 | ❌ | 产物只落本地目录;全库 grep 无 rsync/sftp/ssh/部署代码 | **两站上线都阻塞在这**(台账:"部署阿里云(等凭据)"——凭据之外还缺整个部署器) |
|
||||
| 15 | S3/OSS + CDN 发布(与 14 二选一) | ❌ | MinIO 容器起了但无任何代码使用 | 同上 |
|
||||
| 16 | 表单基础服务 | 🟡 | leads 提交 + zod 校验 + 状态流转 + 审计 | 无垃圾防护/验证码/限流;**邮件通知是 TODO 注释**(设置里有"接收邮箱"字段但不发);无 CRM 转发 |
|
||||
| 17 | 备份、监控和操作日志 | 🟡 | audit_logs 覆盖全部变更端点(actor/before/after/requestId) | **无任何备份脚本**(94MB PG + 1.3GB 媒体全在开发机一块盘上);无监控告警;Fastify logger 关闭;ClickHouse/Redis/MinIO 容器闲置 |
|
||||
|
||||
---
|
||||
|
||||
## 3. cms 超出 V3.0 预期的地方(不要在改造中丢掉)
|
||||
|
||||
1. **WXR 正则解析器**(universal-row.ts):无 XML 库依赖,处理了 `_thumbnail_id`、`_product_image_gallery`、`wppop_sections` PHP 反序列化、Yoast 主分类——这些实战细节 V3.0 只写了方向。
|
||||
2. **WAF/验证码对抗**:REST 通道 202 挑战页快速失败 + 指数退避(30/90/180s)+ 全局节流——SiteGround 拦截是真实踩坑沉淀。
|
||||
3. **三色报告闭环**:externalRef ∪ sitemap 双源对照,🔴missing=0 作为发布关卡已在两站达标。
|
||||
4. **契约测试纪律**:18 事件目录冻结、183 token 全量校验、组件零颜色字面量、WP 文本清洗规则——V3.0 §24 要求的契约测试已有雏形。
|
||||
5. **多语言位**(entry_locales + hreflang 渲染):V3.0 把多语言放到 V1.1,cms 已有编辑位和渲染。
|
||||
|
||||
---
|
||||
|
||||
## 4. 上线前必须处理的五个高危问题(按危险程度排序)
|
||||
|
||||
| # | 问题 | 危险场景 | 修法(对应 V3.0 条目) |
|
||||
|---|---|---|---|
|
||||
| 1 | **构建 seed 兜底**:API 拉取失败时静默用演示数据构建 | control-api 抖动 → 演示内容被构建、过门禁、发布上线 → 线上变成假站 | 构建改为**先冻结输入快照**(拉全量数据 → 落盘 → 校验 → 再构建);失败即中止(V3.0 §13.1) |
|
||||
| 2 | **零备份**:数据库、媒体、产物全在开发机 D 盘 | 磁盘坏 = 两站迁移成果 + 平台数据全灭 | pg_dump 定时 + storage/ 与 .artifacts/ 同步到第二存储;先手动后自动(V3.0 §20) |
|
||||
| 3 | **认证弱**:token 无过期无撤销 + 登录页预填默认凭据 + 无限流 | 部署到公网后管理后台即刻成为攻击面 | token 加过期+撤销表;删除预填凭据并改密;登录限流;MFA 可后置(V3.0 §19.1) |
|
||||
| 4 | **无部署器**:产物出不去本地 | 两站永远"差最后一步"上线 | 实现 rsync/SSH 部署器(先)+ OSS/CDN(后);附带上线检查表(V3.0 附录 A) |
|
||||
| 5 | **重跑覆盖人工编辑**:迁移重跑无条件覆盖 data | 旧站同步时把后台手工修好的内容冲掉 | override 标记 + 冲突队列(V3.0 §8.4) |
|
||||
|
||||
---
|
||||
|
||||
## 5. 改造路线图(C 路线:四梯队)
|
||||
|
||||
### 第一梯队 · 解锁上线与数据安全(立即,1–2 周)
|
||||
1. **部署器 v1**:rsync/SSH 到阿里云 ECS + nginx conf 应用 + 部署记录 + 产物哈希校验 → 把 hesupipe 真正发上线(对齐 V3.0 #14)
|
||||
2. **备份**:每日 pg_dump + storage 增量同步 + 恢复演练一次(对齐 V3.0 #17、§20)
|
||||
3. **构建输入冻结**:移除 seed 兜底;构建前物化站点数据快照;快照哈希进产物元数据(对齐 V3.0 #12、§13.1)
|
||||
4. **认证加固**:token 过期/撤销、清默认凭据、登录限流(对齐 V3.0 #2)
|
||||
|
||||
### 第二梯队 · 平台化核心(3–6 周,magicbridge 复工的前置)
|
||||
5. **主题系统落地**(V3.0 #10/#11,对应 cms 平台化 P2–P4):
|
||||
- templates 表种子 + corporate-pro 主题物化(把现在写死的布局抽成第一套主题)
|
||||
- **打通 token 死线**:让主题 Tab 的编辑真正影响构建产物
|
||||
- Schema 驱动表单(字段类型注册表 → 动态渲染),下线硬编码表单
|
||||
- themes/ 多主题目录 + 按 templateKey 构建(为 magicbridge 汽车站主题做准备)
|
||||
6. **草稿预览**:预览构建目录 + 访问控制 + noindex(V3.0 #13)
|
||||
|
||||
### 第三梯队 · 迁移质量增强(按站需要,穿插进行)
|
||||
7. **差量同步 + 冲突保护**:override 标记、差量分类报告(新增/更新/删除/冲突)、人工修改不被静默覆盖(V3.0 #5)——旧站仍在更新时必需
|
||||
8. **URL 注册表**:redirects 从 settings JSONB 升级为独立表(ERD 本来就这么设计的),补 route_kind/410/查询参数(V3.0 #7)
|
||||
9. **SEO 差异报告**:老站 HTML Head 抓取 vs 新站预览对比,P0–P3 分级接入门禁(V3.0 #8)
|
||||
10. **HTML 爬虫**:链接发现补全 URL 全集(sitemap+WXR+爬虫三源);Playwright 仅按需(V3.0 #4)
|
||||
|
||||
### 第四梯队 · 运营与规模(上线后迭代)
|
||||
11. 表单强化:垃圾防护、邮件通知(消灭 TODO)、CRM 转发(V3.0 #16)
|
||||
12. 监控告警 + 结构化日志 + 构建历史持久化(V3.0 #17)
|
||||
13. WP SQL 第三通道、ACF 字段发现(V3.0 #3 补全)
|
||||
14. event-gateway/ClickHouse 分析栈:**单独决策**——它与建站平台正交,要么砍掉容器要么立项,别挂着
|
||||
|
||||
---
|
||||
|
||||
## 6. 明确不照搬 V3.0 的部分(单人 + AI 模式的取舍)
|
||||
|
||||
| V3.0 设计 | 取舍 | 理由 |
|
||||
|---|---|---|
|
||||
| MFA + 恢复码完整体系 | 后置 | 单运营者;先用强密码 + token 过期 + 限流 + IP 白名单顶住,公网暴露后再上 |
|
||||
| 构建沙箱容器化(断网/限额/无密钥) | 暂缓 | 单人开发无第三方适配器代码风险;**先移除 seed 兜底**(真实风险排序相反) |
|
||||
| CAS 发布锁 / 环境锁 / 租约心跳 | 暂缓 | 单运营者无并发发布冲突;构建单站串行已足够 |
|
||||
| 十来源 URL 全集 | 渐进 | sitemap + WXR + 日志三源已覆盖大半;GSC/GA4 等按站补 |
|
||||
| NestJS + BullMQ 任务队列全家桶 | 观察 | 现状"control-api spawn pnpm"土但能跑;队列在任务变多(定时备份/批量迁移)后再上 |
|
||||
| 5 人团队 20 周排期 | 不适用 | 1 人 + AI 串行;按梯队推进,每梯队以"真实站点闭环"为验收 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 文档与现实偏差清单(建议顺手修正)
|
||||
|
||||
1. `平台化总体设计与实施计划.md` §3:"X-Site-Id 未生效(已知缺陷)"——**已过时**,代码已修复且有 e2e 测试。
|
||||
2. ERD-V1(45 张表、ClickHouse 4 表)是**设计蓝图不是实现**:实际 ORM 是 Drizzle(非 Prisma),redirects 是 settings JSONB(非独立表),site_snapshots/publish_manifests/artifacts/releases 等 ERD 表均未建。
|
||||
3. `services/build-worker`、`services/event-gateway` 是 README 空壳;真实构建在 control-api + astro runtime 脚本里。
|
||||
4. 登录页(admin-web)预填了 `admin@hesupipe.com / hesu-admin-2026`——上线前必须清除。
|
||||
5. docker-compose 的 ClickHouse/Redis/MinIO 无代码消费——要么用起来要么先摘掉,避免"看起来有"的假象。
|
||||
|
||||
---
|
||||
|
||||
## 8. 下一步建议(本周可做)
|
||||
|
||||
1. 部署器 v1 动工前,先向用户/托管方确认:目标形态是阿里云 ECS(nginx)还是 OSS+CDN——决定先写 rsync 还是 OSS 上传。
|
||||
2. 手动做一次全量备份(pg_dump + storage 拷贝到第二块盘/网盘),不等脚本。
|
||||
3. 删除构建 seed 兜底(一行开关级改动,风险最高、成本最低)。
|
||||
4. 把 magicbridge 的主题设计输入(HTML 稿/参考站)排上日程——第二梯队一完成它就能复工。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,249 @@
|
||||
# SiteForge 最小纵向切片 · 设计文档
|
||||
|
||||
> 日期:2026-10-20|状态:待评审
|
||||
> 上位文档:`SiteForge_完整项目计划方案_V3.0.md`(执行基线)
|
||||
> 姊妹文档:`cms现状与SiteForge差距分析_V1.0.md`(D:\project\cms 的教训清单)
|
||||
> 本文决策已经用户逐项确认(建设顺序、切片范围、数据、路线、九项修正)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与定位
|
||||
|
||||
SiteForge 是多站点静态迁移与发布平台(V3.0 定义 17 项必须交付能力)。本切片是整个平台的**第一个里程碑**:用真实试点数据(hesupipe.com 的 WordPress WXR 导出 + 图片包副本)打通最险的核心链路一次:
|
||||
|
||||
```text
|
||||
WXR 导入 → 统一内容模型 → URL 注册表 → 极简主题 → 静态构建 → 门禁 → 本地预览
|
||||
```
|
||||
|
||||
三条前提约束:
|
||||
|
||||
1. **所有代码是正式资产**:数据模型、契约、目录结构按 V3.0 设计,后续能力在此之上加厚,不推倒重写。
|
||||
2. **不改动 D:\project\cms,但白名单资产可移植**(路线 C,2026-10-20 确认):cms 冻结为只读源;试点数据以只读复制方式进入本仓库 `storage/`。**可移植资产(白名单)**:WXR 解析规则与测试夹具(重写到流式 XML 解析器之上)、Astro 页面模板(作为 pilot-minimal 主题起点——其产品 Tabs/相册/表格刚对齐过 hesupipe 老站)、门禁脚本逻辑、docker-compose/CI 配置。**不继承、按 V3.0 重写**:认证、BuildService、release/rollback 脚本、MigrationService 编排(迁移即发布)、settings JSONB 路由、Lead 服务、后台业务页面。
|
||||
3. **完整性由清单驱动**:每完成一个阶段对照 17 项能力清单打钩,全绿才是项目完成;本切片覆盖其中 4 项的骨架(WordPress 导入、统一内容与修订、URL 注册表、Astro 静态构建)。
|
||||
|
||||
**文档权威关系**:`SiteForge_完整项目计划方案_V3.0.md` 是唯一产品与架构基线;`cms现状与SiteForge差距分析_V2.0.md` 是 cms 现状与改造优先级依据(**V1.0 差距分析已作废**);`SiteForge_现有CMS项目复用评估_V1.0.md` 是复用边界参考。
|
||||
|
||||
## 2. 目标与非目标
|
||||
|
||||
### 2.1 目标(本切片交付)
|
||||
|
||||
| # | 交付 | 验收口径 |
|
||||
|---|---|---|
|
||||
| G1 | WXR 全量导入管道(幂等,导入不发布) | hesupipe 全量导入成功(全部为 draft);显式 `publish` 后转 published;重复导入第二次产生 0 条新修订 |
|
||||
| G2 | 统一内容模型 | 产品/新闻/页面落库,不可变修订 + externalRef 幂等键 + checksum |
|
||||
| G3 | URL 注册表与路由策略 | 路径级保真 + 分类/归档/标签处置;URL 对照报告 🔴=0 |
|
||||
| G4 | 极简主题静态构建 | 全站页面 + sitemap.xml + robots.txt + 媒体旧路径输出 |
|
||||
| G5 | 门禁 | 死链=0、sitemap 一致、每页 title/canonical/唯一 H1、产物大小写冲突=0 |
|
||||
| G6 | 本地预览服务器 | 按 route_registry 真实响应(html/301/404),noindex 头 |
|
||||
|
||||
### 2.2 非目标(明确不做,后续阶段做)
|
||||
|
||||
后台管理 UI、部署器(rsync/OSS)、差量同步与冲突队列(本切片只预留 `override` 字段)、SEO 三套数据 diff(P0–P3)、爬虫/Playwright、多语言(en 单语)、表单服务、MFA/认证体系(本地脚本无 HTTP 暴露)、Redis/BullMQ(任务先进程内)。
|
||||
|
||||
## 3. 技术选型与决策记录
|
||||
|
||||
| 决策 | 选择 | 理由(ADR 摘要,正式 ADR 实施时落 docs/adr/) |
|
||||
|---|---|---|
|
||||
| D1 ORM | Drizzle + PostgreSQL 16 | cms 实战验证;迁移即 SQL 可审查;SQL 控制力强(ADR-001) |
|
||||
| D2 任务执行 | 进程内 JobRunner,接口抽象 | 切片无长任务并发需求;接口按 job 语义设计,BullMQ 后置替换不死代码(ADR-002) |
|
||||
| D3 媒体存储 | 本地磁盘 `storage/`,产物保持旧路径 | cms 教训:MinIO 容器起了没人用;对象存储后置(ADR-003) |
|
||||
| D4 URL 策略 | 路径级保真优先,301 兜底 | V3.0 §6/§7 要求;详见 §5(ADR-004) |
|
||||
| D5 服务形态 | NestJS 模块化单体 + CLI 脚本复用服务层 | 架构与 V3.0 一致;切片不启动 HTTP 监听,脚本以 standalone app context 调用模块服务 |
|
||||
| D6 契约范围 | packages/contracts 只含 UniversalRow + 内容/路由 DTO | YAGNI:无队列即无事件目录 |
|
||||
| D7 WXR 解析 | 流式 XML 解析器(saxes 类)+ 资源限额 | cms 的正则解析在 33MB 级 WXR、CDATA/实体/命名空间边界有风险(V2.0 §5.1);限额:文件大小、节点数、处理时限;恶意 XML 防护(ADR-005) |
|
||||
| D8 媒体安全底线 | 登记时魔数校验 + SVG 隔离 | 不信扩展名与声明 MIME;SVG 默认不进产物、单列报告(V2.0 P0-5)(ADR-006) |
|
||||
|
||||
运行环境:Node 22 LTS、pnpm workspace、TypeScript strict、vitest。开发机为 Windows(大小写陷阱见 §7 G5)。
|
||||
|
||||
## 4. 仓库结构(切片实际创建的部分)
|
||||
|
||||
```text
|
||||
cms-one/
|
||||
apps/api/ # NestJS:sites/content/routes/media/import/build/audit 模块
|
||||
packages/contracts/ # UniversalRow、内容 DTO、路由 DTO(冻结+契约测试)
|
||||
packages/adapter-wordpress/ # WXR 解析器 + WP REST 客户端(REST 通道切片内可选)
|
||||
themes/pilot-minimal/ # 极简 Astro 主题
|
||||
scripts/ # CLI:import.ts / build.ts / gate.ts / preview.ts
|
||||
storage/wxr/ storage/media/ # 试点数据副本(git 忽略)
|
||||
infra/docker-compose.yml # 仅 PostgreSQL
|
||||
tests/fixtures/ # WXR/媒体夹具
|
||||
docs/
|
||||
plans/ # 根目录现有 4 份规划文档移入(实施第一步)
|
||||
adr/ specs/ superpowers/
|
||||
.gitignore # 仓库第一个 commit:node_modules/dist/artifacts/storage//.env/coverage
|
||||
```
|
||||
|
||||
不预建空包(cms README 纪律);V3.0 §22.2 的其余包在对应阶段创建。
|
||||
|
||||
## 5. URL 与路由策略(本切片的核心正确性)
|
||||
|
||||
### 5.1 目标路径规则(按优先级)
|
||||
|
||||
| 旧 URL 形态 | 处置 | route_kind |
|
||||
|---|---|---|
|
||||
| 内容页 permalink(含 `.html`/`.php` 后缀、任意目录深度) | **产物按原路径原样输出**(路径级保真,非仅 slug) | html |
|
||||
| 首页 `/` | 首页 | html |
|
||||
| `product-category/{slug}`(产品分类) | 生成分类列表页,路径原样 | html |
|
||||
| `category/{slug}`(文章分类) | 生成文章分类列表页 | html |
|
||||
| 列表分页 `/page/N/`(含分类下分页) | 列表页分页输出 | html |
|
||||
| `tag/{slug}`、`product_tag/{slug}`、日期归档、作者页 | 301 → 对应主列表页(/products/ 或 /news/) | redirect |
|
||||
| 附件/媒体 `wp-content/uploads/...` | 媒体文件按**原路径**进产物 | asset |
|
||||
| 无法保真的个别内容路径 | 301 → 新路径 | redirect |
|
||||
| WP `?p=123` 短链 | 记录为已知限制,对照报告单列(不算 🔴,见 §8) | — |
|
||||
|
||||
### 5.2 route_registry(独立表,禁止塞 settings JSONB——cms 教训)
|
||||
|
||||
切片字段子集(V3.0 §6.4):`site_id / original_path / normalized_lookup_key / route_kind / target_content_id / target_file / redirect_location / indexable / source_status / source_snapshot_id`。
|
||||
|
||||
规范化键规则(仅作查重与对照,原始路径永不改写):percent-decode → Unicode NFC → 小写 → 去尾部斜杠。查重命中仅大小写/尾斜杠差异时**报告冲突**,不静默合并(V3.0 §6.3)。
|
||||
|
||||
### 5.3 URL 对照报告(门禁输入)
|
||||
|
||||
老 URL 全集 = WXR 可推导 URL(内容 permalink ∪ 术语归档 ∪ 分页推导)∪ 老站 sitemap.xml(若可拉取;被挑战页拦截则记说明)。三色口径与 cms 一致:🟢 产物存在同路径页面|🔵 route_registry 有 redirect|🔴 无去处(必须为 0)。
|
||||
|
||||
### 5.4 媒体旧路径保持
|
||||
|
||||
- `media_assets.source_url` 存旧完整 URL,`storage_path` 指向本地副本文件,`public_path` = 旧 URL 路径部分(`/wp-content/uploads/...`)。
|
||||
- 构建时媒体复制到产物的 `public_path` 位置;正文 `<img>`、封面、相册引用全部重写为根相对 `public_path`。
|
||||
- 未匹配到本地副本的媒体:列入导入报告(引用它的页面数、URL 清单),不阻塞导入;若被已发布页面引用则门禁降级为 🔴 由用户决定补图或改链。
|
||||
- 登记时校验文件魔数与声明 MIME 一致,不一致入报告;**SVG 一律隔离**(不复制进产物、预览不可达),报告中单列清单。
|
||||
|
||||
## 6. 管道命令与数据流
|
||||
|
||||
### 6.1 `scripts/import.ts`(导入)
|
||||
|
||||
```text
|
||||
读 storage/wxr/*.xml → adapter-wordpress 解析为 UniversalRow[]
|
||||
→ 类型映射(post→news_article;product CPT→product;page→basic_page)
|
||||
→ locale 取站点配置;未知 locale 记错误并跳过该条(禁止静默归 en——cms 实际踩坑)
|
||||
→ 每条计算 normalized checksum:
|
||||
与最新 content_revision.checksum 相同 → skip(不产生新修订)
|
||||
不同或不存在 → 写入新 content_revision(kind=draft,不可变,source=import)
|
||||
※ 导入不发布:发布是独立显式动作(见 6.2,V2.0 P0-6)
|
||||
→ 媒体登记:按 WXR attachment 的 source_url 与本地副本文件名匹配;
|
||||
全角/编码损坏文件名按规范化通配匹配(cms 踩坑),匹配结果写报告
|
||||
→ 生成/更新 route_registry(§5.1 规则)与 301 规则
|
||||
→ 未知 WP 字段保留进 data.extras(不丢弃)
|
||||
→ 输出导入报告:条目数对照、skip/update/create 计数、媒体匹配率、
|
||||
URL 冲突清单、行级错误定位
|
||||
```
|
||||
|
||||
幂等键:`(site_id, source_connection_id, source_type, source_id, locale)`,与 externalRef(旧 permalink)双保险。
|
||||
|
||||
### 6.2 `scripts/publish.ts`(显式发布)
|
||||
|
||||
导入只产生 draft;发布是独立、显式、可审计的动作(V2.0 P0-6:禁止"迁移即发布"):
|
||||
|
||||
- 按批次/类型/条目批量将 draft 修订置为 published(更新 entry_locales.published_revision_id 指针)。
|
||||
- 每次发布动作写 audit_logs(actor、对象、前后状态、时间)。
|
||||
- 构建只消费 published 修订集合——与 cms「导入后逐条自动发布」的行为刻意相反。
|
||||
|
||||
### 6.3 `scripts/build.ts`(构建)
|
||||
|
||||
```text
|
||||
物化 build_input_snapshot:
|
||||
内容(published 修订集合)+ 路由清单 + 媒体清单 + 站点配置
|
||||
→ 冻结为 artifacts/<buildId>/input/ 下带哈希的 JSON 文件
|
||||
Astro 构建(themes/pilot-minimal):
|
||||
只读输入快照文件,禁止实时查库,禁止任何 seed/演示兜底数据
|
||||
(输入不完整 → 构建立即失败;此行为写回归测试)
|
||||
SITE_URL 取站点配置的生产域名(hesupipe.com)→ canonical/og/sitemap 正确
|
||||
产物:HTML 页面 + sitemap.xml(只含 route_kind=html 且 indexable)+ robots.txt
|
||||
+ 媒体(旧路径)+ _redirects / nginx-redirects.conf(从 route_registry 编译,验证路由模型)
|
||||
+ build-manifest.json(输入快照哈希、页面数、checksums)
|
||||
落 artifacts/<buildId>/,build_jobs 表记录
|
||||
```
|
||||
|
||||
### 6.4 `scripts/gate.ts`(门禁)
|
||||
|
||||
| 检查 | 通过条件 |
|
||||
|---|---|
|
||||
| URL 对照(§5.3) | 🔴 = 0 |
|
||||
| 内部死链 | 产物内 href/src/srcset 指向的内部目标全部存在(html/asset 命中 route_registry) |
|
||||
| sitemap 一致 | sitemap 条目 ⊆ 实际页面;indexable 页面 ⊆ sitemap |
|
||||
| 页面 SEO 基线 | 每页有 title、canonical;H1 至多 1 个 |
|
||||
| 大小写冲突 | 产物相对路径 lowercase 后无重复(Windows 开发盘不敏感、Linux 部署敏感——V3.0 §6.5) |
|
||||
| 重定向图 | route_registry 的 redirect 关系无环;关键路径多跳(≥3 跳)告警(V2.0 §5.3:🔴=0 不代表无环) |
|
||||
| 兜底数据回归 | 输入损坏时构建必须失败(负向测试) |
|
||||
|
||||
### 6.5 `scripts/preview.ts`(预览)
|
||||
|
||||
自研 Node 静态服务器(不引入 nginx 依赖):
|
||||
|
||||
- 按 route_registry 响应:html → 伺服产物文件;redirect → 301 + Location;无匹配 → 产物 404 页。
|
||||
- 所有响应加 `X-Robots-Tag: noindex`;禁用目录列表。
|
||||
- 用途:在本地验证"真实 URL 行为"(V3.0 §7.4 精神),并支撑 §8 的人工抽检。
|
||||
|
||||
## 7. 数据模型(切片子集,V3.0 §9 对齐)
|
||||
|
||||
| 表 | 关键字段与约束 |
|
||||
|---|---|
|
||||
| sites | site_id PK、name、default_locale、production_domain |
|
||||
| source_connections | 类型=wxr、文件路径 + sha256、adapter 版本 |
|
||||
| import_jobs / source_records | 批次状态机;源记录存原始条目位置 + checksum + 解析状态 |
|
||||
| content_entries | (site_id, type_key, external_ref) 唯一;status: draft/published/archived |
|
||||
| entry_locales | (site_id, locale, slug) 唯一;current/published_revision_id 指针 |
|
||||
| content_revisions | **不可变**(插入式,禁 UPDATE);data jsonb、checksum、source=import、import_batch_id;预留 `overridden_fields`(下阶段冲突队列用) |
|
||||
| route_registry | §5.2 字段;独立表 |
|
||||
| media_assets | (site_id, source_url) 唯一幂等;sha256、public_path(旧路径)、alt、尺寸 |
|
||||
| build_jobs / artifacts | 构建记录 + 产物目录 + 输入快照哈希 |
|
||||
| audit_logs | 追加式;actor(切片为 system/importer)、action、对象、前后值 |
|
||||
|
||||
多语言位:模型带 locale,切片只写 en。
|
||||
|
||||
## 8. 错误处理
|
||||
|
||||
- **行级容错**:单条解析/映射失败记录行号与原因后继续;整批结构错误(文件损坏、站点不存在)才中断。
|
||||
- **未知字段**:一律进 `data.extras` 保留,报告中汇总清单。
|
||||
- **构建 fail-fast**:输入快照不完整(内容缺失、路由空、媒体引用悬空)立即失败,无任何降级/兜底路径。
|
||||
- **已知限制**:`?p=` 短链、WXR 外的老站 URL(日志/GSC 来源)不在本切片对照范围,报告中单列"未覆盖来源"节——不算 🔴,进入下阶段 SEO diff。
|
||||
- **重跑语义**:无变化 skip / 有变化新修订 / 人工改动保护(override 标记)下阶段实现,本切片在修订上预留字段。
|
||||
|
||||
## 9. 测试策略(vitest)
|
||||
|
||||
| 层 | 内容 |
|
||||
|---|---|
|
||||
| 单元:WXR 解析 | 夹具必须覆盖:`_thumbnail_id`、`_product_image_gallery`、`wppop_sections`(PHP serialize 的 Tab 数据)、Yoast `_yoast_wpseo_title/metadesc`、全角/编码损坏文件名、分页与术语 URL 推导、`.html` 后缀 permalink(全部来自 cms 实际踩坑清单) |
|
||||
| 单元:路由规则 | §5.1 每行规则一个用例;大小写/尾斜杠冲突报告 |
|
||||
| 单元:解析器限额 | 超大/畸形 XML(节点数、大小、时限超限)→ 明确失败不崩溃;CDATA、实体、命名空间边界夹具 |
|
||||
| 单元:媒体安全 | 魔数与扩展名不符 → 报告;SVG → 进隔离清单 |
|
||||
| 单元:重定向图 | 环 → 🔴;多跳 → 告警 |
|
||||
| 集成:导入 | 真实 WXR 小切片夹具 → 落库 → 断言修订/checksum/幂等(第二次 0 新修订) |
|
||||
| 集成:构建 | 快照物化 → Astro 构建 → 产物结构断言(sitemap/robots/媒体旧路径/_redirects) |
|
||||
| 负向 | 输入损坏 → 构建失败(兜底禁令);route_registry 缺目标 → 门禁 🔴 |
|
||||
| 契约 | UniversalRow/DTO 字段冻结(packages/contracts) |
|
||||
| 验收 | §2.1 G1–G6 全部可执行复验(真实 hesupipe 数据 + 抽检 20 个 URL:10 内容页 + 5 分类页 + 3 redirect + 2 404) |
|
||||
|
||||
## 10. 实施注意(从 cms 教训直接落地的防线)
|
||||
|
||||
0. **动工第零步**:手动备份 cms 数据(pg_dump + storage/ 拷贝至第二存储,约半小时——V2.0 阶段 A 要求)。
|
||||
1. `.gitignore` 是仓库第一个 commit(storage/、artifacts/、node_modules、.env)。
|
||||
2. 构建输入快照先于一切(seed 兜底事故的根治)。
|
||||
3. redirects 走独立表(不进 settings JSONB)。
|
||||
4. WXR 原件 + sha256 留档 source_connections。
|
||||
5. 未知字段不丢弃(extras)。
|
||||
6. 门禁 🔴=0 才算过。
|
||||
7. Windows 长路径:副本拷贝与构建脚本启用长路径处理(全角文件名目录)。
|
||||
|
||||
## 11. 验收标准(切片完成的定义)
|
||||
|
||||
> 口径采用 V2.0 §2.2 成熟度分级:本切片验收 = **L3(真实数据本地验证)**;L4(生产部署、HTTP 验收、回滚演练)属后续部署阶段。
|
||||
|
||||
1. `import` 两连跑:第一次全量入库为 draft(条目数与 WXR 基数对照一致),`publish` 后转 published,第二次 import 0 新修订。
|
||||
2. `build` 产出全站产物,`gate` 七项全绿。
|
||||
3. `preview` 启动后按 §9 抽检 20 URL 行为正确(含 301 跳转与 404)。
|
||||
4. `pnpm test` 全绿(含负向与契约)。
|
||||
5. 导入报告与 URL 对照报告可读、可复查(含媒体匹配率与未覆盖来源说明)。
|
||||
|
||||
## 12. 切片之后的路(指引后续子项目,不在本切片内)
|
||||
|
||||
```text
|
||||
SP0' 后台 UI(Art Design Pro + 认证/MFA)
|
||||
SP1' 差量同步与冲突队列(override 字段启用)
|
||||
SP2' SEO 三套数据 diff(P0–P3)+ 爬虫扩充 URL 全集
|
||||
SP3' 主题/板块协议(Block Schema/模板约束/第二主题)
|
||||
SP4' 部署器(rsync/SSH → OSS/CDN)+ 发布锁/回滚
|
||||
SP5' 表单服务 + 备份监控
|
||||
```
|
||||
|
||||
每阶段对照 `cms现状与SiteForge差距分析_V1.0.md` 的 17 项清单打钩。
|
||||
Reference in New Issue
Block a user