Files
jiahong e303bb868a 更新
2026-03-22 15:19:22 +08:00

34 KiB
Raw Permalink Blame History

文档生产及输出管理 — 规划设计及实施方案

一、概述

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 页面:

  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 导出 有权限用户可导出 PDFPandoc + 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 发表评论和反馈 truelogin/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 的定位是轻量防护,适用于营销试读、内容预览等场景。高价值内容建议使用 loginrestricted 级别。


七、阅读统计分析

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_viewspublic_oncemax_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 自动发布流程

@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 短链接 营销短信文案 系统默认浏览器打开

链接格式示例:

完整 URLhttps://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 周