960 lines
34 KiB
Markdown
960 lines
34 KiB
Markdown
# 文档生产及输出管理 — 规划设计及实施方案
|
||
|
||
## 一、概述
|
||
|
||
### 1.1 目标
|
||
|
||
基于 [ICT 服务平台](ICT服务平台概要.md) 的统一认证底座(OpenLDAP + Keycloak)和 Git 基础设施(Gitea),构建**从 Markdown 编写到浏览器阅读、反馈、统计分析**的全链路文档管理平台,覆盖文档生产、发布、阅读、协作、运营的完整生命周期。
|
||
|
||
### 1.2 核心设计原则
|
||
|
||
- **Git 为唯一真实源**:所有文档以 Markdown 格式存储于 Git 仓库,浏览器端为只读渲染视图
|
||
- **开源优先**:核心组件全部采用成熟开源方案,降低成本与锁定风险
|
||
- **认证复用**:登录用户接入 ICT 平台 Keycloak SSO 免密码秘钥登录;游客与访客免登录,通过浏览器指纹追踪
|
||
- **自动化驱动**:Git 推送即触发渲染、发布、同步,零人工干预
|
||
|
||
### 1.3 用户角色
|
||
|
||
| 角色 | 说明 | 典型场景 |
|
||
|------|------|---------|
|
||
| 作者 (Author) | 拥有 Git 仓库写权限的员工 | VS Code / Qoder 编写 Markdown 并推送 |
|
||
| 审阅者 (Reviewer) | 受邀阅读并点评文档的内部/外部人员 | 浏览器阅读、点评、反馈 |
|
||
| 读者 (Reader) | 通过 Keycloak 登录后访问文档的注册用户 | 登录后阅读 `login` / `restricted` 级别文档 |
|
||
| 游客 (Guest) | 免登录访问公开文档的匿名用户 | 通过 URL 自由阅读 `public` 级别文档,可匿名评论 |
|
||
| 访客 (Visitor) | 免登录仅限一次阅读的匿名用户 | 首次打开 `public_once` 级别文档可阅读,再次访问需登录 |
|
||
| 管理员 (Admin) | 管理发布策略、权限、生命周期的 IT 人员 | 配置发布规则与权限策略 |
|
||
|
||
---
|
||
|
||
## 二、系统架构
|
||
|
||
### 2.1 整体架构图
|
||
|
||
```plantuml
|
||
@startuml
|
||
skinparam componentStyle rectangle
|
||
title 文档生产及输出管理 — 系统架构
|
||
|
||
actor "作者" as Author
|
||
actor "游客/访客/读者" as Reader
|
||
|
||
node "VS Code + Qoder" as VSCode
|
||
|
||
node "互联网应用服务器 (腾讯云/阿里云)" as AppServer {
|
||
component "Nginx + SSL" as Nginx
|
||
component "Keycloak SSO" as KC
|
||
|
||
package "文档生产" {
|
||
component "Gitea" as Gitea
|
||
component "DocForge" as Forge
|
||
}
|
||
|
||
package "文档阅读" {
|
||
component "DocPortal" as Portal
|
||
component "MeiliSearch" as Search
|
||
}
|
||
|
||
package "协作与运营" {
|
||
component "Remark42" as Comment
|
||
component "Umami" as Analytics
|
||
component "MsgHub" as MsgHub
|
||
}
|
||
}
|
||
|
||
node "私有云 [数据后端]" as PCloud {
|
||
database "PostgreSQL" as DB
|
||
database "OpenLDAP" as LDAP
|
||
storage "Git 仓库存储" as Store
|
||
}
|
||
|
||
node "目标域名网站" as Sites {
|
||
component "yink.ai" as SiteA
|
||
component "docs.writech.cn" as SiteB
|
||
}
|
||
|
||
' == 作者流 ==
|
||
Author -down-> VSCode : Markdown 编写
|
||
VSCode -down-> Gitea : git push (SSH)
|
||
Gitea -down-> Store : 仓库数据
|
||
|
||
' == 渲染发布 ==
|
||
Gitea -right-> Forge : Webhook
|
||
Forge -right-> Portal : HTML + 摘要
|
||
Forge -down-> DB : 元数据入库
|
||
Forge ..> Sites : 自动部署
|
||
|
||
' == 读者流 ==
|
||
Reader -down-> Nginx : HTTPS
|
||
Nginx --> KC : 认证
|
||
Nginx --> Portal : 文档路由
|
||
|
||
' == 阅读交互 ==
|
||
Portal --> Comment : 评论
|
||
Portal --> Analytics : 访问记录
|
||
Portal --> Search : 搜索
|
||
|
||
' == 内部数据流 ==
|
||
Comment -right-> MsgHub : 评论通知
|
||
MsgHub -down-> DB : 消息存储
|
||
KC -down-> LDAP : 用户认证
|
||
@enduml
|
||
```
|
||
|
||
### 2.2 核心组件清单
|
||
|
||
| 组件 | 开源方案 | 用途 | 许可证 |
|
||
|------|---------|------|--------|
|
||
| Git 仓库 | **Gitea** | 文档源码存储与版本管理 | MIT |
|
||
| Markdown 渲染 | **Pandoc** + **markdown-it** | Markdown → HTML 转换,元数据提取 | GPL / MIT |
|
||
| 阅读平台 | **自研 DocPortal**(基于 Next.js) | 文档浏览、权限控制、URL 管理 | — |
|
||
| 评论系统 | **Remark42** | 自托管评论,支持匿名/认证评论 | MIT |
|
||
| 统计分析 | **Umami** | 自托管网站分析,页面访问与阅读时长 | MIT |
|
||
| 全文检索 | **MeiliSearch** | 文档标题、摘要、正文全文搜索 | MIT |
|
||
| PDF 导出 | **Pandoc** + **WeasyPrint** | Markdown → PDF 高质量排版 | GPL |
|
||
| 消息推送 | **自研 MsgHub**(基于 Socket.io) | 实时消息通知与任务看板集成 | — |
|
||
| 认证中心 | **Keycloak**(已有) | OIDC SSO 统一登录 | Apache 2.0 |
|
||
| 反向代理 | **Nginx**(已有) | SSL 终止、路由分发 | BSD |
|
||
| 静态站点生成 | **MkDocs** / **Hugo** | Git → 静态网站自动构建 | BSD / Apache |
|
||
| 浏览器指纹 | **FingerprintJS** (开源版) | 访客匿名标识,`public_once` 一次性阅读控制 | MIT |
|
||
|
||
---
|
||
|
||
## 三、文档生产流程
|
||
|
||
### 3.1 编写工具:VS Code + Qoder
|
||
|
||
- 作者使用 **VS Code** 编辑器 + **Qoder** AI 辅助工具进行 Markdown 文档编写
|
||
- 支持实时预览、AI 辅助补全、PlantUML 图表嵌入
|
||
- 所有文档遵循统一的 Markdown 规范(标题层级、Front Matter 元数据等)
|
||
|
||
### 3.2 Front Matter 元数据规范
|
||
|
||
每篇文档头部须包含 YAML Front Matter,声明文档元信息:
|
||
|
||
```yaml
|
||
---
|
||
title: "产品技术方案"
|
||
summary: "描述智能笔 BLE 通信协议的整体架构与关键技术细节"
|
||
author: "zhangsan@writech.cn"
|
||
tags: ["技术方案", "智能笔", "BLE"]
|
||
publish:
|
||
access: login # 可选:public / public_once / login / restricted
|
||
allowed_users: [] # access=restricted 时生效,填写用户邮箱
|
||
permissions: # 各权限开关
|
||
read: true
|
||
comment: true
|
||
save_as: false
|
||
export_pdf: false
|
||
lifecycle:
|
||
expires_at: "2026-06-30" # 可选:到期日期
|
||
max_views: null # 可选:最大阅读次数
|
||
---
|
||
```
|
||
|
||
### 3.3 Git 推送触发流程
|
||
|
||
```
|
||
作者在 VS Code / Qoder 中编写 Markdown
|
||
│
|
||
├─ git add → git commit → git push (SSH 秘钥认证)
|
||
│
|
||
└─ Gitea 接收推送
|
||
│
|
||
├─ Webhook → DocForge 渲染引擎
|
||
│ ├─ 解析 Front Matter 元数据
|
||
│ ├─ Markdown → HTML 渲染(Pandoc + markdown-it)
|
||
│ ├─ 提取摘要(首段 / summary 字段)
|
||
│ ├─ 生成文档 URL(基于仓库路径映射)
|
||
│ ├─ 写入文档注册表(PostgreSQL)
|
||
│ ├─ 推送到 MeiliSearch 索引
|
||
│ └─ 若匹配域名映射规则 → 同步到目标网站
|
||
│
|
||
└─ 文档在 DocPortal 即时可访问
|
||
```
|
||
|
||
---
|
||
|
||
## 四、文档渲染与发布引擎(DocForge)
|
||
|
||
### 4.1 渲染流程
|
||
|
||
DocForge 是 Git Webhook 驱动的文档处理服务,负责将 Markdown 转换为可发布的 HTML 页面:
|
||
|
||
1. **接收 Webhook**:Gitea 推送事件触发,包含变更文件列表
|
||
2. **增量渲染**:仅处理本次变更的 Markdown 文件,非全量重建
|
||
3. **元数据解析**:提取 Front Matter 中的标题、摘要、权限、生命周期配置
|
||
4. **HTML 渲染**:通过 Pandoc 将 Markdown 转为带目录的 HTML,嵌入统一样式模板
|
||
5. **摘要生成**:优先使用 `summary` 字段,未填则自动取正文前 200 字
|
||
6. **URL 生成规则**:`https://docs.writech.cn/{仓库名}/{文档路径}`
|
||
7. **注册入库**:文档元数据(URL、标题、摘要、权限、生命周期)写入 PostgreSQL
|
||
8. **搜索索引**:文档标题 + 摘要 + 正文推送至 MeiliSearch
|
||
|
||
### 4.2 渲染引擎技术栈
|
||
|
||
```
|
||
DocForge (Node.js 服务)
|
||
├─ Express.js — HTTP 接收 Webhook
|
||
├─ Pandoc (CLI 调用) — Markdown → HTML 核心渲染
|
||
├─ markdown-it — 辅助渲染(代码高亮、PlantUML 等)
|
||
├─ gray-matter — Front Matter 解析
|
||
├─ pg (node-postgres) — 元数据写入 PostgreSQL
|
||
└─ meilisearch-js — 搜索索引更新
|
||
```
|
||
|
||
---
|
||
|
||
## 五、文档阅读平台(DocPortal)
|
||
|
||
### 5.1 功能概览
|
||
|
||
DocPortal 是面向读者的 Web 应用,提供文档浏览、搜索、评论、导出等功能:
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| 文档列表 | 按仓库/标签/时间浏览文档,显示标题 + 摘要 + URL |
|
||
| 全文搜索 | 基于 MeiliSearch 的标题、摘要、正文即时搜索 |
|
||
| 文档阅读 | 渲染后的 HTML 页面,带目录导航 |
|
||
| 评论反馈 | 嵌入 Remark42 评论组件,支持分段评论 |
|
||
| PDF 导出 | 有权限用户可导出 PDF(Pandoc + WeasyPrint) |
|
||
| 另存为 | 有权限用户可下载 Markdown 原文或 HTML |
|
||
| 源文件定位 | 有编辑权限的用户可见「编辑源文件」图标,一键复制 Git 仓库中对应 Markdown 文件的完整路径 |
|
||
|
||
### 5.2 URL 与摘要体系
|
||
|
||
每篇文档发布后具备:
|
||
|
||
| 元素 | 格式 | 示例 |
|
||
|------|------|------|
|
||
| 文档 URL | `https://docs.writech.cn/{repo}/{path}` | `https://docs.writech.cn/docs/技术方案/BLE通信协议` |
|
||
| 短链接 | `https://docs.writech.cn/d/{短码}` | `https://docs.writech.cn/d/a3Kx9` |
|
||
| 摘要 | Front Matter `summary` 或自动提取前 200 字 | 显示在文档列表、搜索结果、分享卡片中 |
|
||
|
||
短链接便于在邮件、即时通讯中分享,访问短链接自动重定向到完整 URL。
|
||
|
||
### 5.3 源文件快速定位(编辑图标)
|
||
|
||
对于拥有 Git 仓库写权限的用户,文档页面右上角显示 **「✏️ 编辑源文件」** 图标:
|
||
|
||
- **点击**:复制 Git 仓库中对应 Markdown 文件的完整路径到剪贴板,如 `docs/技术方案/BLE通信协议.md`
|
||
- **Tooltip**:显示仓库名 + 文件路径 + 最近修改者 + 修改时间
|
||
- 作者可直接在 VS Code / Qoder 中通过路径定位文件并修改
|
||
|
||
---
|
||
|
||
## 六、权限管理体系
|
||
|
||
### 6.1 文档访问级别
|
||
|
||
文档发布时,作者在 Front Matter 的 `publish.access` 字段选择访问级别:
|
||
|
||
| 级别 | 标识 | 说明 |
|
||
|------|------|------|
|
||
| **公开** | `public` | 游客可通过 URL 自由访问,无需登录,不限次数 |
|
||
| **公开一次** | `public_once` | 访客免登录可阅读一次,再次访问同一文档需登录;通过浏览器指纹 + Cookie 判定 |
|
||
| **需登录** | `login` | 需通过 Keycloak 登录后方可访问(读者 / 审阅者) |
|
||
| **限定人员** | `restricted` | 仅 `allowed_users` 列表中的用户可访问 |
|
||
|
||
### 6.2 细粒度权限矩阵
|
||
|
||
在 `publish.permissions` 中按功能逐项配置:
|
||
|
||
| 权限 | 说明 | 默认值 |
|
||
|------|------|--------|
|
||
| `read` | 阅读文档正文 | true |
|
||
| `comment` | 发表评论和反馈 | true(login/restricted);public 游客可匿名评论(需验证码);public_once 访客不可评论 |
|
||
| `save_as` | 下载 Markdown 原文或 HTML | false(游客 / 访客始终不可用) |
|
||
| `export_pdf` | 导出为 PDF 文件 | false(游客 / 访客始终不可用) |
|
||
|
||
### 6.3 权限校验流程
|
||
|
||
```plantuml
|
||
@startuml
|
||
skinparam componentStyle rectangle
|
||
title 文档访问权限校验流程
|
||
|
||
start
|
||
:用户访问文档 URL;
|
||
|
||
if (文档 access = public ?) then (是)
|
||
:允许阅读;
|
||
note right: 游客 - 免登录, 不限次数
|
||
else (否)
|
||
if (文档 access = public_once ?) then (是)
|
||
if (用户已登录 ?) then (是)
|
||
:允许阅读;
|
||
note right: 登录用户不受一次限制
|
||
else (否)
|
||
:生成浏览器指纹;
|
||
if (已有该文档访问记录 ?) then (是)
|
||
:提示 "请登录后继续访问";
|
||
:重定向到 Keycloak 登录;
|
||
stop
|
||
else (否)
|
||
:允许阅读;
|
||
:写入指纹记录 + Cookie;
|
||
note right: 访客 - 免登录, 仅此一次
|
||
endif
|
||
endif
|
||
else (否)
|
||
if (用户已登录 Keycloak ?) then (否)
|
||
:重定向到 Keycloak 登录;
|
||
stop
|
||
else (是)
|
||
if (文档 access = login ?) then (是)
|
||
:允许阅读;
|
||
else (restricted)
|
||
if (用户在 allowed_users 列表中 ?) then (是)
|
||
:允许阅读;
|
||
else (否)
|
||
:返回 403 无权访问;
|
||
stop
|
||
endif
|
||
endif
|
||
endif
|
||
endif
|
||
endif
|
||
|
||
:加载文档页面;
|
||
:根据角色与 permissions 决定功能可用性;
|
||
note right
|
||
游客: 可匿名评论(需验证码), 不可导出
|
||
访客: 不可评论, 不可导出
|
||
登录用户: 按 permissions 配置
|
||
编辑图标: 仅 Git 写权限用户
|
||
end note
|
||
stop
|
||
@enduml
|
||
```
|
||
|
||
### 6.4 权限与认证底座的关系
|
||
|
||
| 层次 | 组件 | 职责 |
|
||
|------|------|------|
|
||
| 身份源 | OpenLDAP(私有云) | 用户账户、组织架构、角色 |
|
||
| 认证中心 | Keycloak(互联网服务器) | SSO 登录,签发 OIDC Token |
|
||
| 匿名访问控制 | DocPortal + FingerprintJS | 游客自由访问 `public` 文档;访客通过浏览器指纹 + Cookie 判定是否首次访问 `public_once` 文档 |
|
||
| 应用层权限 | DocPortal | 解析登录用户 Token 或匿名身份,匹配 Front Matter 权限配置 |
|
||
| Git 写权限 | Gitea | 判断用户是否有仓库写权限,控制「编辑图标」显示 |
|
||
|
||
### 6.5 访客一次性阅读的技术实现
|
||
|
||
`public_once` 级别文档的访客身份追踪方案:
|
||
|
||
| 技术手段 | 说明 |
|
||
|---------|------|
|
||
| FingerprintJS | 客户端浏览器指纹库,生成稳定的匿名标识符(无需 Cookie 即可识别回访) |
|
||
| HttpOnly Cookie | 辅助手段,首次阅读时种下 Cookie,防止清除指纹后绕过限制 |
|
||
| 服务端记录 | PostgreSQL 存储 `(fingerprint_hash, doc_id, visited_at)`,校验是否已阅读 |
|
||
|
||
校验流程:用户访问 `public_once` 文档时,DocPortal 前端通过 FingerprintJS 生成浏览器指纹,携带指纹向后端查询是否已有该文档的访问记录;无记录则放行并写入,有记录则提示登录。
|
||
|
||
> **注意**:浏览器指纹并非 100% 可靠(更换浏览器或隐身模式可重置),`public_once` 的定位是**轻量防护**,适用于营销试读、内容预览等场景。高价值内容建议使用 `login` 或 `restricted` 级别。
|
||
|
||
---
|
||
|
||
## 七、阅读统计分析
|
||
|
||
### 7.1 采集指标
|
||
|
||
基于 **Umami**(自托管 Web 分析)采集以下数据:
|
||
|
||
| 指标 | 采集方式 | 说明 |
|
||
|------|---------|------|
|
||
| 页面访问量(PV) | Umami JS 埋点 | 每次打开文档 URL 计一次 |
|
||
| 独立访客数(UV) | Umami 匿名指纹 | 去重统计独立访问用户(含游客 / 访客匿名指纹) |
|
||
| 阅读时长 | Umami 页面停留时间 + 自定义心跳事件 | 每 30 秒上报一次心跳,计算有效阅读时长 |
|
||
| 阅读进度 | 自定义事件(滚动百分比) | 记录用户阅读到文档的哪个位置 |
|
||
| 来源渠道 | Umami Referrer | 记录用户从哪个链接进入 |
|
||
|
||
### 7.2 阅读时长精确统计方案
|
||
|
||
标准的页面停留时间统计不够准确(用户可能切出标签页),采用**心跳 + 可见性检测**方案:
|
||
|
||
```javascript
|
||
// 嵌入文档页面的阅读时长统计脚本(伪代码)
|
||
let readingSeconds = 0;
|
||
let heartbeatTimer = null;
|
||
|
||
document.addEventListener('visibilitychange', () => {
|
||
if (document.hidden) {
|
||
clearInterval(heartbeatTimer); // 页面不可见,暂停计时
|
||
} else {
|
||
heartbeatTimer = setInterval(() => {
|
||
readingSeconds += 30;
|
||
umami.track('reading-heartbeat', { // 每30秒上报
|
||
doc_id: DOC_ID,
|
||
seconds: readingSeconds
|
||
});
|
||
}, 30000);
|
||
}
|
||
});
|
||
```
|
||
|
||
### 7.3 统计看板
|
||
|
||
管理员和作者可在 DocPortal 中查看文档统计看板:
|
||
|
||
- **文档维度**:每篇文档的 PV / UV / 平均阅读时长 / 完读率
|
||
- **时间维度**:按日 / 周 / 月查看趋势
|
||
- **用户维度**:(需登录文档)哪些用户阅读了、阅读时长排名
|
||
- **导出**:统计数据可导出 CSV
|
||
|
||
---
|
||
|
||
## 八、文档生命周期管理
|
||
|
||
### 8.1 生命周期配置
|
||
|
||
在 Front Matter 的 `publish.lifecycle` 中配置:
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `expires_at` | 日期字符串 | 到期后文档自动下架,页面显示「文档已过期」 |
|
||
| `max_views` | 整数 | 累计阅读次数达到上限后自动下架 |
|
||
| 无配置 | — | 永久有效,不自动下架 |
|
||
|
||
> **区分 `max_views` 与 `public_once`**:`max_views` 是文档级总阅读次数上限(达到后所有用户均不可访问),`public_once` 是访客级单次阅读限制(每位访客仅限免登录阅读一次,登录用户不受影响)。两者可同时配置、互不冲突。
|
||
|
||
### 8.2 生命周期状态流转
|
||
|
||
```
|
||
已发布 (Active)
|
||
│
|
||
├─ 达到 expires_at → 已过期 (Expired)
|
||
├─ 达到 max_views → 已达上限 (Limit Reached)
|
||
├─ 作者手动下架 → 已下架 (Archived)
|
||
└─ Git 中删除文件 → 已删除 (Deleted)
|
||
|
||
已过期 / 已达上限 / 已下架
|
||
└─ 作者更新 Front Matter 重新配置 → 已发布 (Active)
|
||
```
|
||
|
||
### 8.3 下架处理
|
||
|
||
- 下架后 URL 仍保留,但页面显示提示信息(如「此文档已过期,请联系作者」)
|
||
- 管理员可配置是否允许已登录用户查看过期文档的历史快照
|
||
- 文档的统计数据和评论不随下架删除,可供作者回溯
|
||
|
||
---
|
||
|
||
## 九、评论反馈系统
|
||
|
||
### 9.1 技术方案:Remark42
|
||
|
||
采用 **Remark42** 自托管评论系统:
|
||
|
||
- **部署位置**:互联网应用服务器(Docker 容器)
|
||
- **认证对接**:通过 Keycloak OIDC 实现评论者身份认证
|
||
- **匿名评论**:`public` 级别文档支持游客匿名评论(需验证码防刷);`public_once` 级别文档访客不开放评论
|
||
- **数据存储**:Remark42 自带 BoltDB 存储,备份至私有云
|
||
|
||
### 9.2 评论功能
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| 文档级评论 | 在文档末尾发表整体评论 |
|
||
| 段落级评论 | 选中文档段落后发表针对性评论 |
|
||
| 回复与嵌套 | 支持多级回复讨论 |
|
||
| @提及 | 评论中 @某用户,触发专属通知 |
|
||
| Markdown 格式 | 评论内容支持 Markdown 语法 |
|
||
| 管理操作 | 作者可置顶、删除评论;管理员可全局管理 |
|
||
|
||
### 9.3 评论触发消息通知
|
||
|
||
当文档收到新评论或反馈时:
|
||
|
||
1. Remark42 通过 Webhook 通知 MsgHub 消息中心
|
||
2. MsgHub 根据评论内容识别通知目标:
|
||
- 文档作者(始终通知)
|
||
- 被 @提及的用户
|
||
- 该文档评论帖的参与者(可配置是否通知)
|
||
3. 消息实时推送到目标用户的消息中心
|
||
|
||
---
|
||
|
||
## 十、消息中心与任务看板集成
|
||
|
||
### 10.1 设计理念
|
||
|
||
消息中心采用**类微信群列表**的交互模式:
|
||
|
||
- 每篇有新消息的文档如同一个「对话」
|
||
- 新消息驱动该文档条目**置顶排列**(最新消息在最前)
|
||
- 点击文档条目直接在浏览器中打开对应文档及其评论区
|
||
- 未读消息显示红点 + 未读数
|
||
- 消息中心同时作为作者的**任务看板**,待处理的评论/反馈一目了然
|
||
|
||
### 10.2 消息类型
|
||
|
||
| 消息类型 | 触发条件 | 消息内容 |
|
||
|---------|---------|---------|
|
||
| 📝 新评论 | 文档收到新评论 | "{用户}在《{文档标题}》中发表了评论" |
|
||
| 💬 回复 | 某人回复了你的评论 | "{用户}回复了你在《{文档标题}》中的评论" |
|
||
| @提及 | 评论中 @了你 | "{用户}在《{文档标题}》的评论中提到了你" |
|
||
| 📊 阅读里程碑 | 文档阅读量突破阈值 | "《{文档标题}》阅读量已突破 100 次" |
|
||
| ⚠️ 生命周期告警 | 文档即将过期或达到阅读上限 | "《{文档标题}》将于 3 天后过期" |
|
||
|
||
### 10.3 消息中心界面结构
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 📬 消息中心 🔍 搜索 │
|
||
├─────────────────────────────────────────┤
|
||
│ 🔴 BLE通信协议技术方案 10:32 │
|
||
│ 张三:建议补充低功耗模式的说明 │
|
||
├─────────────────────────────────────────┤
|
||
│ 🔴 产品需求文档 v2.1 09:15 │
|
||
│ 李四 回复了你的评论 │
|
||
├─────────────────────────────────────────┤
|
||
│ 智能笔固件升级指南 昨天 │
|
||
│ 阅读量已突破 100 次 │
|
||
├─────────────────────────────────────────┤
|
||
│ Q3 项目计划 周一 │
|
||
│ 王五:时间节点需要再确认 │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
- 红点标识未读消息
|
||
- 列表按最新消息时间倒序排列
|
||
- 点击任一条目 → 浏览器打开该文档页面,自动滚动到对应评论
|
||
- 支持标记已读、批量已读、按类型筛选
|
||
|
||
### 10.4 技术实现
|
||
|
||
```
|
||
MsgHub 消息中心 (Node.js)
|
||
├─ Socket.io — WebSocket 实时推送
|
||
├─ PostgreSQL — 消息持久化存储
|
||
├─ Redis — 未读计数缓存、在线状态
|
||
├─ Remark42 Webhook — 评论事件接入
|
||
├─ DocForge Webhook — 生命周期事件接入
|
||
└─ Umami API — 阅读量里程碑检测
|
||
```
|
||
|
||
---
|
||
|
||
## 十一、域名网站自动发布
|
||
|
||
### 11.1 映射机制
|
||
|
||
Git 仓库中的 Markdown 可配置自动发布到指定域名网站,映射关系存储于 PostgreSQL:
|
||
|
||
| Git 仓库 / 路径 | 目标域名 | 构建工具 | 说明 |
|
||
|-----------------|---------|---------|------|
|
||
| `web-doc/` | yink.ai | Hugo | 品牌官网内容 |
|
||
| `docs/对外文档/` | docs.writech.cn | MkDocs | 对外技术文档站 |
|
||
| `edu-doc/` | edu.writech.cn | MkDocs | 教育平台文档 |
|
||
|
||
### 11.2 自动发布流程
|
||
|
||
```plantuml
|
||
@startuml
|
||
skinparam componentStyle rectangle
|
||
title Git → 域名网站自动发布流程
|
||
|
||
start
|
||
:作者 git push 更新 Markdown;
|
||
:Gitea Webhook 触发 DocForge;
|
||
|
||
:DocForge 检查变更文件路径;
|
||
if (匹配域名映射规则 ?) then (是)
|
||
:调用对应构建工具\n(Hugo / MkDocs);
|
||
:生成静态 HTML 站点;
|
||
:通过 rsync + SSH\n部署到目标服务器;
|
||
:目标域名网站内容更新;
|
||
else (否)
|
||
:仅更新 DocPortal\n内部阅读平台;
|
||
endif
|
||
|
||
stop
|
||
@enduml
|
||
```
|
||
|
||
### 11.3 映射配置文件
|
||
|
||
映射关系通过 Git 仓库中的配置文件 `.docforge.yml` 管理:
|
||
|
||
```yaml
|
||
# .docforge.yml — 仓库根目录
|
||
site_mappings:
|
||
- source: "对外文档/"
|
||
target:
|
||
domain: "docs.writech.cn"
|
||
builder: "mkdocs"
|
||
deploy:
|
||
method: "rsync"
|
||
host: "106.55.191.177"
|
||
path: "/var/www/docs.writech.cn/"
|
||
- source: "/"
|
||
target:
|
||
domain: "docs.writech.cn"
|
||
builder: "mkdocs"
|
||
base_path: "/internal/"
|
||
deploy:
|
||
method: "rsync"
|
||
host: "106.55.191.177"
|
||
path: "/var/www/docs.writech.cn/internal/"
|
||
```
|
||
|
||
映射关系一旦设定,后续 Markdown 更新即自动推送到对应域名,无需手动操作。
|
||
|
||
---
|
||
|
||
## 十二、互联网推广与海报链接体系
|
||
|
||
### 12.1 设计目标
|
||
|
||
将文档系统产出的内容转化为**互联网营销落地页**(海报链接),通过主流流量平台分发,获取 2B / 2C 新客户。核心链路:
|
||
|
||
```
|
||
文档系统 (Markdown)
|
||
│
|
||
├─ DocForge 渲染为静态 HTML 落地页
|
||
│
|
||
├─ 内嵌 JS 与服务器 API 交互(埋点 / 表单 / 动态内容)
|
||
│
|
||
├─ CDN 全网加速分发
|
||
│
|
||
├─ 生成海报链接(短链接 + 渠道追踪参数)
|
||
│
|
||
└─ 投放到微信 / 淘宝 / 美团 / 抖音 / 短信
|
||
│
|
||
└─ 客户点击/扫码 → 浏览器打开落地页 → 转化
|
||
```
|
||
|
||
### 12.2 海报链接架构
|
||
|
||
#### 落地页结构
|
||
|
||
海报链接指向的是一张**静态 HTML 落地页**,由 DocForge 从 Markdown 源文档自动生成,包含:
|
||
|
||
| 层次 | 内容 | 说明 |
|
||
|------|------|------|
|
||
| 静态 HTML | 产品介绍、图文排版、CTA 按钮 | CDN 分发,毫秒级加载 |
|
||
| 内嵌 JS | 埋点脚本 + 交互逻辑 | 页面加载后调用服务器 API |
|
||
| 服务器 API | 渠道统计、表单提交、动态内容 | 运行在互联网应用服务器 |
|
||
|
||
#### 落地页内嵌 JS 交互能力
|
||
|
||
静态落地页加载后,内嵌的 JS 脚本自动调用服务器接口完成以下交互:
|
||
|
||
```javascript
|
||
// 落地页内嵌 JS 核心逻辑(伪代码)
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
|
||
// 1. 渠道来源埋点 — 记录用户从哪个平台进入
|
||
const params = new URLSearchParams(location.search);
|
||
fetch('/api/promo/track', {
|
||
method: 'POST',
|
||
body: JSON.stringify({
|
||
page_id: PAGE_ID,
|
||
channel: params.get('ch'), // wx / tb / mt / dy / sms
|
||
campaign: params.get('cmp'), // 活动标识
|
||
referer: document.referrer
|
||
})
|
||
});
|
||
|
||
// 2. 动态内容加载 — 价格、库存、活动信息
|
||
fetch('/api/promo/dynamic/' + PAGE_ID)
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
document.getElementById('price').textContent = data.price;
|
||
document.getElementById('stock').textContent = data.stock;
|
||
});
|
||
|
||
// 3. 表单提交 — 客户留资 / 咨询 / 预约
|
||
document.getElementById('lead-form').addEventListener('submit', (e) => {
|
||
e.preventDefault();
|
||
fetch('/api/promo/lead', {
|
||
method: 'POST',
|
||
body: new FormData(e.target)
|
||
});
|
||
});
|
||
});
|
||
```
|
||
|
||
### 12.3 CDN 全网加速分发
|
||
|
||
落地页为纯静态 HTML + CSS + JS + 图片,通过 CDN 分发到全网边缘节点,确保各渠道用户点击后毫秒级加载:
|
||
|
||
| 项目 | 方案 | 说明 |
|
||
|------|------|------|
|
||
| CDN 服务 | 阿里云 CDN | 覆盖国内及海外节点,配合已有域名架构 |
|
||
| 源站 | 互联网应用服务器 | DocForge 生成的静态文件存储于源站 |
|
||
| 缓存策略 | HTML 5分钟 / 图片字体 30 天 | HTML 短缓存确保内容更新及时生效 |
|
||
| HTTPS | ZeroSSL 通配符证书 | 复用 ICT 平台证书体系 |
|
||
| 缓存刷新 | DocForge 发布后自动调用 CDN Purge API | Markdown 更新后落地页即时刷新 |
|
||
|
||
发布流程:
|
||
|
||
```
|
||
DocForge 渲染落地页 HTML
|
||
│
|
||
├─ 写入源站目录 /var/www/promo/
|
||
│
|
||
├─ 调用阿里云 CDN Purge API 刷新缓存
|
||
│
|
||
└─ 全网边缘节点同步更新(秒级)
|
||
```
|
||
|
||
### 12.4 五大渠道投放方案
|
||
|
||
每个渠道生成专属海报链接,带渠道追踪参数,确保来源可精确归因:
|
||
|
||
| 渠道 | 渠道码 | 链接形式 | 投放载体 | 打开方式 |
|
||
|------|---------|---------|---------|----------|
|
||
| **微信** | `ch=wx` | 短链接 + 二维码 | 朋友圈图文、公众号文章、群聊卡片 | 微信内置浏览器打开 |
|
||
| **淘宝** | `ch=tb` | 淘口令 + 短链接 | 商品详情页、店铺首页、客服消息 | 手淘内置浏览器打开 |
|
||
| **美团** | `ch=mt` | 短链接 | 店铺介绍、团购详情、评价回复 | 美团 App 内置浏览器打开 |
|
||
| **抖音** | `ch=dy` | 短链接 | 视频评论区、主页链接、直播间小黄车 | 抖音内置浏览器打开 |
|
||
| **短信** | `ch=sms` | 短链接 | 营销短信文案 | 系统默认浏览器打开 |
|
||
|
||
链接格式示例:
|
||
|
||
```
|
||
完整 URL:https://go.writech.cn/p/smart-pen-intro?ch=wx&cmp=2026q1
|
||
短链接: https://go.writech.cn/s/Xk9mP
|
||
淘口令: ¥smart-pen-introXk9mP¥
|
||
二维码: 将短链接编码为 QR Code,嵌入海报图片
|
||
```
|
||
|
||
### 12.5 渠道适配与浏览器兼容
|
||
|
||
各平台客户端点击链接后均通过其**内置浏览器**打开落地页,需针对性适配:
|
||
|
||
| 内置浏览器 | 特征 | 适配策略 |
|
||
|-------------|------|----------|
|
||
| 微信 WebView | 不支持部分 Web API,有 JS-SDK | 检测 UA 含 "MicroMessenger",加载微信 JS-SDK,启用分享卡片自定义 |
|
||
| 淘宝 WebView | 限制外跳,访问受限 | 落地页自包含,避免外跳;表单交互在页内完成 |
|
||
| 美团 WebView | 与标准浏览器接近 | 标准响应式适配即可 |
|
||
| 抖音 WebView | 限制外跳,支持基础 Web API | 落地页自包含;复杂交互引导“用浏览器打开” |
|
||
| 系统浏览器 (短信) | 完整 Web 能力 | 无需特殊适配 |
|
||
|
||
落地页 JS 自动检测运行环境并适配:
|
||
|
||
```javascript
|
||
// 环境检测与适配(伪代码)
|
||
const ua = navigator.userAgent;
|
||
if (/MicroMessenger/i.test(ua)) {
|
||
loadWxJSSDK(); // 加载微信 JS-SDK,配置分享卡片
|
||
} else if (/AliApp.*TB/i.test(ua)) {
|
||
disableExternalLinks(); // 淘宝内禁止外跳
|
||
} else if (/aweme/i.test(ua)) {
|
||
showOpenInBrowser(); // 抖音内显示“用浏览器打开”引导
|
||
}
|
||
```
|
||
|
||
### 12.6 推广流量追踪与转化分析
|
||
|
||
#### 追踪参数体系
|
||
|
||
每个海报链接携带统一追踪参数,全部流入 Umami 统计平台:
|
||
|
||
| 参数 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `ch` | 渠道来源 | wx / tb / mt / dy / sms |
|
||
| `cmp` | 活动标识 | 2026q1 / summer-sale |
|
||
| `ct` | 内容类型 | product / article / event |
|
||
| `kw` | 关键词(付费投放时) | smart-pen / ink-screen |
|
||
|
||
#### 转化漏斗
|
||
|
||
从点击到转化的全链路数据均录入 PostgreSQL,供营销团队分析:
|
||
|
||
```
|
||
点击链接 (Impression)
|
||
│
|
||
├─ 打开落地页 (PageView) ← Umami 埋点
|
||
│
|
||
├─ 页面停留 > 10s (Engaged) ← 心跳上报
|
||
│
|
||
├─ 提交表单 / 点击 CTA (Lead) ← 表单提交 API
|
||
│
|
||
└─ 完成购买 / 注册 (Conversion) ← 业务系统回调
|
||
```
|
||
|
||
#### 推广效果看板
|
||
|
||
在 DocPortal 管理后台提供推广效果看板:
|
||
|
||
| 维度 | 指标 |
|
||
|------|------|
|
||
| 渠道维度 | 各渠道 PV / UV / 平均停留 / 留资数 / 转化率 |
|
||
| 内容维度 | 各落地页访问量 / 转化率 / 热度图 |
|
||
| 活动维度 | 各活动投入产出比 (ROI) |
|
||
| 时间维度 | 按日 / 周 / 月的流量与转化趋势 |
|
||
|
||
### 12.7 推广落地页生成与管理流程
|
||
|
||
```plantuml
|
||
@startuml
|
||
skinparam componentStyle rectangle
|
||
title 推广落地页生成与分发流程
|
||
|
||
start
|
||
:营销人员在 Markdown 中编写推广内容;
|
||
note right: 使用 promo 模板,配置表单/CTA
|
||
|
||
:设置 Front Matter 推广配置;
|
||
note right
|
||
publish.type: promo
|
||
publish.channels: [wx, tb, dy]
|
||
publish.cdn: true
|
||
end note
|
||
|
||
:git push 推送到 Gitea;
|
||
:DocForge 渲染生成静态落地页;
|
||
note right
|
||
内嵌埋点 JS + 表单交互 JS
|
||
生成各渠道专属短链接
|
||
微信渠道额外生成 QR Code
|
||
end note
|
||
|
||
:部署到源站 + CDN 刷新;
|
||
|
||
:营销人员获取各渠道链接;
|
||
note right
|
||
微信: 短链接 + QR Code
|
||
淘宝: 淘口令 + 短链接
|
||
美团: 短链接
|
||
抖音: 短链接
|
||
短信: 短链接
|
||
end note
|
||
|
||
:投放到各平台;
|
||
|
||
:客户点击/扫码;
|
||
:平台内置浏览器打开落地页;
|
||
note right
|
||
CDN 加速加载静态 HTML
|
||
JS 调用服务器 API 记录渠道+加载动态内容
|
||
end note
|
||
|
||
:客户浏览/交互/留资;
|
||
:Umami + API 记录全链路数据;
|
||
stop
|
||
@enduml
|
||
```
|
||
|
||
### 12.8 推广文档 Front Matter 扩展
|
||
|
||
推广类文档在标准 Front Matter 基础上增加推广专属配置:
|
||
|
||
```yaml
|
||
---
|
||
title: "智能笔新品发布"
|
||
summary: "自然写 Qink 智能笔,笔迹实时同步至大屏"
|
||
author: "marketing@writech.cn"
|
||
tags: ["推广", "智能笔", "Qink"]
|
||
publish:
|
||
type: promo # 推广类型文档
|
||
access: public # 推广页通常 public;高价值预览内容可用 public_once
|
||
cdn: true # 启用 CDN 分发
|
||
channels: [wx, tb, mt, dy, sms] # 投放渠道
|
||
landing_page:
|
||
template: product # 落地页模板:product / article / event
|
||
cta_text: "立即了解" # CTA 按钮文案
|
||
cta_url: "/contact" # CTA 跳转目标
|
||
form: true # 是否包含留资表单
|
||
lifecycle:
|
||
expires_at: "2026-06-30"
|
||
---
|
||
```
|
||
|
||
---
|
||
|
||
## 十三、部署方案
|
||
|
||
### 13.1 服务部署清单
|
||
|
||
全部服务运行于**互联网应用服务器**(腾讯云 / 阿里云),数据后端在私有云:
|
||
|
||
| 服务 | 部署方式 | 运行位置 | 端口 |
|
||
|------|---------|---------|------|
|
||
| DocForge 渲染引擎 | Docker | 互联网应用服务器 | 3001 |
|
||
| DocPortal 阅读平台 | Docker (Next.js) | 互联网应用服务器 | 3000 |
|
||
| Remark42 评论系统 | Docker | 互联网应用服务器 | 8080 |
|
||
| Umami 统计分析 | Docker | 互联网应用服务器 | 3002 |
|
||
| MeiliSearch 搜索 | Docker | 互联网应用服务器 | 7700 |
|
||
| MsgHub 消息中心 | Docker (Node.js) | 互联网应用服务器 | 3003 |
|
||
| Redis | Docker | 互联网应用服务器 | 6379 |
|
||
| PostgreSQL | 原生安装 | 私有云 | 5432 |
|
||
| Gitea | Docker(已有) | 互联网应用服务器 | 22/443 |
|
||
| Keycloak | Docker(已有) | 互联网应用服务器 | 8443 |
|
||
| PromoAPI 推广接口 | Docker (Node.js) | 互联网应用服务器 | 3004 |
|
||
| 阿里云 CDN | SaaS | 全网边缘节点 | — |
|
||
|
||
### 13.2 Nginx 路由规则
|
||
|
||
```nginx
|
||
# DocPortal 阅读平台
|
||
location /docs/ {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
}
|
||
|
||
# Remark42 评论 API
|
||
location /api/comment/ {
|
||
proxy_pass http://127.0.0.1:8080;
|
||
}
|
||
|
||
# Umami 统计
|
||
location /api/analytics/ {
|
||
proxy_pass http://127.0.0.1:3002;
|
||
}
|
||
|
||
# MeiliSearch 搜索
|
||
location /api/search/ {
|
||
proxy_pass http://127.0.0.1:7700;
|
||
}
|
||
|
||
# MsgHub WebSocket
|
||
location /ws/msg/ {
|
||
proxy_pass http://127.0.0.1:3003;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
}
|
||
|
||
# DocForge Webhook(仅允许 Gitea 内部调用)
|
||
location /hook/docforge {
|
||
allow 127.0.0.1;
|
||
deny all;
|
||
proxy_pass http://127.0.0.1:3001;
|
||
}
|
||
|
||
# PromoAPI 推广接口
|
||
location /api/promo/ {
|
||
proxy_pass http://127.0.0.1:3004;
|
||
}
|
||
|
||
# 推广落地页静态文件(CDN 回源)
|
||
location /p/ {
|
||
alias /var/www/promo/;
|
||
expires 5m;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 十四、实施路线图
|
||
|
||
| 阶段 | 任务 | 预计周期 |
|
||
|------|------|--------|
|
||
| **第一阶段:基础** | DocForge 渲染引擎开发,Gitea Webhook 对接 | 第 1-2 周 |
|
||
| **第一阶段** | DocPortal 阅读平台 MVP(文档列表 + 阅读 + URL + 摘要) | 第 2-3 周 |
|
||
| **第一阶段** | MeiliSearch 全文检索集成 | 第 3 周 |
|
||
| **第一阶段** | Front Matter 权限解析 + Keycloak OIDC 认证对接 | 第 3-4 周 |
|
||
| **第二阶段:协作** | Remark42 评论系统部署与 Keycloak 对接 | 第 5 周 |
|
||
| **第二阶段** | MsgHub 消息中心开发(WebSocket + 消息列表) | 第 5-6 周 |
|
||
| **第二阶段** | 消息中心与任务看板集成(类微信列表交互) | 第 6-7 周 |
|
||
| **第二阶段** | 评论通知 → 消息中心 → 打开文档全链路打通 | 第 7 周 |
|
||
| **第三阶段:运营** | Umami 统计分析部署,阅读时长精确统计方案 | 第 8 周 |
|
||
| **第三阶段** | 文档生命周期管理(过期、阅读上限、自动下架) | 第 8-9 周 |
|
||
| **第三阶段** | PDF 导出功能(Pandoc + WeasyPrint) | 第 9 周 |
|
||
| **第四阶段:发布** | 域名网站自动发布(.docforge.yml 映射 + Hugo/MkDocs 构建) | 第 10-11 周 |
|
||
| **第四阶段** | 统计看板(作者维度 + 文档维度 + 趋势图) | 第 11-12 周 |
|
||
| **第四阶段** | 全链路测试与上线 | 第 12 周 |
|
||
| **第五阶段:推广** | 推广落地页模板开发 + CDN 接入 | 第 13 周 |
|
||
| **第五阶段** | 五渠道海报链接生成 + 渠道埋点 + 浏览器适配 | 第 13-14 周 |
|
||
| **第五阶段** | 推广效果看板(渠道归因 + 转化漏斗) | 第 14 周 |
|