34 KiB
文档生产及输出管理 — 规划设计及实施方案
一、概述
1.1 目标
基于 ICT 服务平台 的统一认证底座(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 整体架构图
@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,声明文档元信息:
---
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 页面:
- 接收 Webhook:Gitea 推送事件触发,包含变更文件列表
- 增量渲染:仅处理本次变更的 Markdown 文件,非全量重建
- 元数据解析:提取 Front Matter 中的标题、摘要、权限、生命周期配置
- HTML 渲染:通过 Pandoc 将 Markdown 转为带目录的 HTML,嵌入统一样式模板
- 摘要生成:优先使用
summary字段,未填则自动取正文前 200 字 - URL 生成规则:
https://docs.writech.cn/{仓库名}/{文档路径} - 注册入库:文档元数据(URL、标题、摘要、权限、生命周期)写入 PostgreSQL
- 搜索索引:文档标题 + 摘要 + 正文推送至 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 权限校验流程
@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 阅读时长精确统计方案
标准的页面停留时间统计不够准确(用户可能切出标签页),采用心跳 + 可见性检测方案:
// 嵌入文档页面的阅读时长统计脚本(伪代码)
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 评论触发消息通知
当文档收到新评论或反馈时:
- Remark42 通过 Webhook 通知 MsgHub 消息中心
- MsgHub 根据评论内容识别通知目标:
- 文档作者(始终通知)
- 被 @提及的用户
- 该文档评论帖的参与者(可配置是否通知)
- 消息实时推送到目标用户的消息中心
十、消息中心与任务看板集成
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 自动发布流程
@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 管理:
# .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 脚本自动调用服务器接口完成以下交互:
// 落地页内嵌 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 自动检测运行环境并适配:
// 环境检测与适配(伪代码)
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 推广落地页生成与管理流程
@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 基础上增加推广专属配置:
---
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 路由规则
# 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 周 |