darkeril

design

DocHub - 项目文档管理系统技术设计

版本:v1.0 | 日期:2026-02-16 | 状态:设计阶段

1. 系统概述

DocHub 是一个面向小团队的项目文档管理系统,支持 Markdown 文档编写、任务看板、文档分享和 AI 写入。替代现有简易 Markdown Viewer,覆盖项目全生命周期。

2. 系统架构

┌─────────────────────────────────────────────────────────┐
│                      Caddy 反向代理                       │
│                  docs.ycapis.com :443                     │
└──────────────────────┬──────────────────────────────────┘

┌──────────────────────▼──────────────────────────────────┐
│                   Node.js + Express                      │
│                     Port 3100                            │
│                                                          │
│  ┌─────────┐  ┌──────────┐  ┌─────────┐  ┌───────────┐ │
│  │ Auth    │  │ Doc API  │  │ Task API│  │ Share API │ │
│  │MiddleW  │  │ CRUD+搜索 │  │ 看板CRUD │  │ 公开链接  │ │
│  └─────────┘  └──────────┘  └─────────┘  └───────────┘ │
│  ┌─────────┐  ┌──────────┐  ┌─────────────────────────┐ │
│  │ AI API  │  │ Project  │  │   Static File Server    │ │
│  │ Bearer  │  │ API      │  │   (Vue 3 SPA)           │ │
│  └─────────┘  └──────────┘  └─────────────────────────┘ │
└──────────────────────┬──────────────────────────────────┘
          ┌────────────┼────────────┐
          ▼            ▼            ▼
   ┌──────────┐ ┌──────────┐ ┌──────────┐
   │  SQLite  │ │ .md 文件  │ │ 全文索引  │
   │ 元数据DB │ │ 本地存储  │ │ (SQLite  │
   │          │ │          │ │  FTS5)   │
   └──────────┘ └──────────┘ └──────────┘

核心设计决策

  • 文档双存储:元数据存 SQLite,内容存 .md 文件。便于 Git 管理和 AI 直接读写
  • 单进程架构:Express 服务同时提供 API 和静态文件,PM2 管理
  • 文件系统布局/root/Projects/doc-system/data/projects/{slug}/docs/*.md

3. 技术选型

层级选择理由
前端框架Vue 3 + Vite与现有 Markdown Viewer 技术栈一致,范总团队熟悉
UI 框架TailwindCSS + Headless UI快速开发响应式界面,无需重 UI 库
后端Node.js + Express延续现有架构,简单可靠
数据库SQLite (better-sqlite3)零运维,单文件备份,FTS5 全文搜索
Markdownmarkdown-it + highlight.js + mermaidmarkdown-it 插件生态丰富,扩展性强于 marked
编辑器CodeMirror 6轻量(~150KB),移动端友好,比 Monaco 小 5 倍
进程管理PM2已在用,自动重启 + 日志
反向代理Caddy已有,自动 HTTPS

4. 数据库 Schema

-- 用户表
CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  password_hash TEXT NOT NULL,
  role TEXT NOT NULL DEFAULT 'viewer',  -- 'admin' | 'viewer'
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 项目表
CREATE TABLE projects (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  slug TEXT UNIQUE NOT NULL,           -- URL 友好标识,如 'ycapi'
  description TEXT,
  icon TEXT DEFAULT '📁',              -- emoji 图标
  color TEXT DEFAULT '#3B82F6',        -- 主题色
  sort_order INTEGER DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 文档表
CREATE TABLE documents (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
  parent_id INTEGER REFERENCES documents(id) ON DELETE SET NULL,  -- 目录结构
  title TEXT NOT NULL,
  slug TEXT NOT NULL,                  -- 文件名(不含 .md)
  type TEXT DEFAULT 'doc',             -- 'folder' | 'doc'
  doc_type TEXT DEFAULT 'general',     -- 'requirement' | 'design' | 'api' | 'plan' | 'report' | 'meeting' | 'general'
  file_path TEXT,                      -- 相对于 data/ 的 .md 文件路径
  sort_order INTEGER DEFAULT 0,
  created_by INTEGER REFERENCES users(id),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 全文搜索虚拟表
CREATE VIRTUAL TABLE documents_fts USING fts5(
  title, content,
  content=documents,
  content_rowid=id
);

-- 任务表
CREATE TABLE tasks (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  description TEXT,
  status TEXT DEFAULT 'todo',          -- 'todo' | 'doing' | 'done'
  priority INTEGER DEFAULT 0,          -- 0=普通, 1=重要, 2=紧急
  sort_order INTEGER DEFAULT 0,
  due_date DATE,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 分享链接表
CREATE TABLE shares (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  document_id INTEGER NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  token TEXT UNIQUE NOT NULL,          -- UUID,用于公开访问
  password TEXT,                       -- 可选访问密码
  expires_at DATETIME,                 -- 可选过期时间
  view_count INTEGER DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 索引
CREATE UNIQUE INDEX idx_doc_project_slug ON documents(project_id, parent_id, slug);
CREATE INDEX idx_tasks_project_status ON tasks(project_id, status);
CREATE INDEX idx_shares_token ON shares(token);

5. 文件系统布局

/root/Projects/doc-system/
├── DESIGN.md              # 本文件
├── package.json
├── server/
│   ├── index.js           # 入口
│   ├── db.js              # SQLite 连接 + 初始化
│   ├── auth.js            # 认证中间件
│   ├── routes/
│   │   ├── auth.js        # POST /api/auth/login, /logout
│   │   ├── projects.js    # CRUD /api/projects
│   │   ├── documents.js   # CRUD /api/projects/:slug/docs
│   │   ├── tasks.js       # CRUD /api/projects/:slug/tasks
│   │   ├── shares.js      # 分享管理
│   │   ├── search.js      # GET /api/search?q=
│   │   └── ai.js          # AI 写入接口
│   └── utils/
│       ├── markdown.js    # 服务端 MD 渲染(用于搜索索引)
│       └── migrate.js     # 导入现有文档
├── client/                # Vue 3 SPA
│   ├── src/
│   │   ├── App.vue
│   │   ├── router.js
│   │   ├── views/
│   │   │   ├── Dashboard.vue      # 首页仪表板
│   │   │   ├── Project.vue        # 项目页(文档树+内容)
│   │   │   ├── DocView.vue        # 文档渲染
│   │   │   ├── DocEdit.vue        # 编辑器
│   │   │   ├── Kanban.vue         # 任务看板
│   │   │   ├── SharedDoc.vue      # 公开分享页
│   │   │   ├── Login.vue
│   │   │   └── Settings.vue
│   │   ├── components/
│   │   │   ├── Sidebar.vue
│   │   │   ├── DocTree.vue
│   │   │   ├── MarkdownRenderer.vue
│   │   │   ├── Editor.vue         # CodeMirror 封装
│   │   │   ├── TaskCard.vue
│   │   │   └── SearchModal.vue
│   │   └── composables/
│   │       ├── useAuth.js
│   │       └── useApi.js
│   └── vite.config.js
├── data/
│   ├── dochub.db          # SQLite 数据库
│   └── projects/
│       ├── ycapi/
│       │   └── docs/
│       │       ├── business-plan.md
│       │       └── api-design.md
│       ├── banxiang/
│       │   └── docs/
│       └── meet5-research/
│           └── docs/
└── ecosystem.config.js    # PM2 配置

6. API 设计

6.1 认证

方法路径说明
POST/api/auth/login登录,返回 session cookie
POST/api/auth/logout登出
GET/api/auth/me当前用户信息

6.2 项目

方法路径说明
GET/api/projects项目列表
POST/api/projects创建项目 🔒
GET/api/projects/:slug项目详情
PUT/api/projects/:slug更新项目 🔒
DELETE/api/projects/:slug删除项目 🔒

6.3 文档

方法路径说明
GET/api/projects/:slug/docs文档树
POST/api/projects/:slug/docs创建文档 🔒
GET/api/projects/:slug/docs/:docSlug获取文档(含 Markdown 内容)
PUT/api/projects/:slug/docs/:docSlug更新文档 🔒
DELETE/api/projects/:slug/docs/:docSlug删除文档 🔒
PATCH/api/projects/:slug/docs/:docSlug/move移动/排序 🔒

6.4 任务

方法路径说明
GET/api/projects/:slug/tasks任务列表(支持 ?status= 过滤)
POST/api/projects/:slug/tasks创建任务 🔒
PUT/api/projects/:slug/tasks/:id更新任务 🔒
DELETE/api/projects/:slug/tasks/:id删除任务 🔒
PATCH/api/projects/:slug/tasks/:id/move拖拽移动(更新 status + sort_order)🔒

6.5 分享

方法路径说明
POST/api/shares创建分享链接 🔒
GET/api/shares管理分享列表 🔒
DELETE/api/shares/:id撤销分享 🔒
GET/s/:token公开访问分享文档(无需登录)

6.6 搜索

方法路径说明
GET/api/search?q=关键词&project=slug全文搜索(FTS5)

6.7 AI 写入接口

使用 Bearer Token 认证,供 AI(露露)自动操作文档。

方法路径说明
POST/api/ai/docs创建/更新文档
GET/api/ai/docs/:project/:docSlug读取文档
POST/api/ai/tasks创建任务
PATCH/api/ai/tasks/:id更新任务状态

AI 创建文档示例:

POST /api/ai/docs
Authorization: Bearer <AI_TOKEN>
Content-Type: application/json

{
  "project": "ycapi",
  "title": "API 接口设计 v2",
  "slug": "api-design-v2",
  "doc_type": "api",
  "parent": "design",
  "content": "# API 接口设计 v2\n\n..."
}

响应:

{
  "ok": true,
  "doc": { "id": 15, "slug": "api-design-v2", "url": "/projects/ycapi/docs/api-design-v2" }
}

7. 页面设计

7.1 首页/仪表板

┌──────────────────────────────────────────────────┐
│  🏠 DocHub                    🔍 搜索    👤 范总  │
├──────────────────────────────────────────────────┤
│                                                  │
│  我的项目                                         │
│                                                  │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐   │
│  │ 🚀 ycapi   │ │ 🤝 伴享     │ │ 🔍 Meet5   │   │
│  │            │ │ 银发社交    │ │ 调研       │   │
│  │ 12 文档    │ │ 8 文档     │ │ 5 文档     │   │
│  │ 3 进行中   │ │ 1 进行中   │ │ 0 任务     │   │
│  └────────────┘ └────────────┘ └────────────┘   │
│                                                  │
│  最近更新                                         │
│  • ycapi/商业计划书 v3        2h ago              │
│  • 伴享/竞品分析              昨天                │
│  • Meet5/调研报告             3天前               │
└──────────────────────────────────────────────────┘

7.2 项目页

┌──────────────────────────────────────────────────┐
│  ← DocHub / ycapi                 🔍  📋看板  ⚙️  │
├────────────┬─────────────────────────────────────┤
│ 📂 文档     │                                     │
│            │  # 商业计划书 v3                      │
│ ▼ 📁 商业   │                                     │
│   📄 计划书 │  ## 1. 项目概述                      │
│   📄 财务   │                                     │
│ ▼ 📁 设计   │  ycapi 是一个面向...                 │
│   📄 架构   │                                     │
│   📄 API   │  ```mermaid                         │
│ ▼ 📁 需求   │  graph LR                           │
│   📄 v1.0  │    A-->B                             │
│            │  ```                                 │
│ ──────────│                                      │
│ + 新建文档  │  [✏️ 编辑] [🔗 分享] [🗑️ 删除]       │
└────────────┴─────────────────────────────────────┘

7.3 编辑页

┌──────────────────────────────────────────────────┐
│  编辑: 商业计划书 v3          [💾 保存] [✖ 取消]   │
├─────────────────────┬────────────────────────────┤
│ # 商业计划书 v3     │  商业计划书 v3(渲染)       │
│                    │                             │
│ ## 1. 项目概述      │  1. 项目概述                 │
│                    │                             │
│ ycapi 是一个面向... │  ycapi 是一个面向...         │
│                    │                             │
│ (CodeMirror 编辑器) │  (实时 Markdown 预览)       │
└─────────────────────┴────────────────────────────┘

7.4 看板页

┌──────────────────────────────────────────────────┐
│  ycapi 任务看板                        + 新建任务  │
├────────────────┬────────────────┬────────────────┤
│ 📋 待办 (3)    │ 🔄 进行中 (2)   │ ✅ 已完成 (5)  │
│                │                │                │
│ ┌────────────┐│ ┌────────────┐│ ┌────────────┐ │
│ │ 支付接口    ││ │ 用户注册    ││ │ 数据库设计  │ │
│ │ 🔴 紧急     ││ │ 🟡 重要     ││ │            │ │
│ │ 2/20 截止  ││ │            ││ │            │ │
│ └────────────┘│ └────────────┘│ └────────────┘ │
│ ┌────────────┐│ ┌────────────┐│                │
│ │ 商品管理    ││ │ API 文档    ││                │
│ └────────────┘│ └────────────┘│                │
│               │                │                │
│ (支持拖拽)     │                │                │
└────────────────┴────────────────┴────────────────┘

7.5 移动端适配

  • 文档树改为抽屉式侧边栏(汉堡菜单触发)
  • 编辑器全屏,预览通过 Tab 切换
  • 看板改为单列滑动切换
  • 底部 Tab 导航:首页 / 项目 / 搜索 / 设置

8. 关键实现细节

8.1 Markdown 渲染管线

import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import mermaid from 'mermaid'

const md = new MarkdownIt({
  html: true,
  linkify: true,
  highlight: (str, lang) => {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(str, { language: lang }).value
    }
    return ''
  }
})

// Mermaid 插件:将 ```mermaid 代码块渲染为图表
md.use(mermaidPlugin)
// 任务列表插件
md.use(taskListPlugin)
// 数学公式(可选)
md.use(katexPlugin)

8.2 全文搜索

利用 SQLite FTS5,文档保存时同步更新索引:

// 更新索引
db.prepare(`
  INSERT INTO documents_fts(rowid, title, content)
  VALUES (?, ?, ?)
`).run(docId, title, plainTextContent)

// 搜索
db.prepare(`
  SELECT d.*, snippet(documents_fts, 1, '<mark>', '</mark>', '...', 30) as snippet
  FROM documents_fts f
  JOIN documents d ON d.id = f.rowid
  WHERE documents_fts MATCH ?
  ORDER BY rank
  LIMIT 20
`).all(query)

8.3 权限模型

管理员 (admin):所有操作

访客 (viewer):仅通过分享链接查看特定文档

AI Token:通过 Bearer Token 访问 /api/ai/* 端点
  • 管理员通过 session cookie 认证
  • 分享链接通过 URL token 认证(/s/:token
  • AI 通过 Authorization: Bearer <token> 认证
  • AI Token 存储在环境变量 AI_API_TOKEN

8.4 现有文档迁移

编写迁移脚本,自动导入现有 Markdown 文件:

// server/utils/migrate.js
const imports = [
  { source: '/root/Projects/business-plan/', project: 'ycapi', name: 'ycapi 商业计划' },
  { source: '/root/Projects/meet5-research/', project: 'meet5-research', name: 'Meet5 调研' },
]
// 遍历 .md 文件,创建项目 + 文档记录,复制文件到 data/projects/

9. 部署配置

Caddy 配置

docs.ycapis.com {
    reverse_proxy localhost:3100
}

PM2 配置

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'dochub',
    script: 'server/index.js',
    env: {
      NODE_ENV: 'production',
      PORT: 3100,
      SESSION_SECRET: '<random-secret>',
      AI_API_TOKEN: '<ai-token-for-lulu>',
      ADMIN_PASSWORD: '<admin-password>'
    }
  }]
}

首次部署

cd /root/Projects/doc-system
npm install
cd client && npm install && npm run build && cd ..
node server/utils/migrate.js   # 导入现有文档
pm2 start ecosystem.config.js

10. 开发计划

第一阶段:核心骨架(3-4 天)

任务预估
项目脚手架(Express + Vue 3 + Vite)0.5 天
SQLite 数据库初始化 + Schema0.5 天
认证(登录/登出/session)0.5 天
项目 CRUD API + 首页仪表板0.5 天
文档 CRUD API + 文件读写1 天
文档树组件 + 项目页0.5 天
Markdown 渲染(highlight.js + mermaid)0.5 天

第二阶段:编辑与看板(2-3 天)

任务预估
CodeMirror 6 编辑器集成1 天
实时预览(左右分栏)0.5 天
任务看板 API + 前端1 天
拖拽排序(看板 + 文档树)0.5 天

第三阶段:分享与搜索(1-2 天)

任务预估
分享链接生成 + 公开页面0.5 天
FTS5 全文搜索 + 搜索 UI0.5 天
AI 写入 API0.5 天

第四阶段:完善与部署(1-2 天)

任务预估
响应式/移动端适配0.5 天
现有文档迁移脚本0.5 天
Caddy 配置 + PM2 部署0.5 天
导航页更新0.5 天

总计:7-11 天(Codex 辅助开发可压缩至 4-6 天)

11. 未来扩展(不在本期)

  • 多用户协作编辑(WebSocket + OT/CRDT)
  • 文档版本历史(Git 或快照表)
  • 文件附件上传(图片等)
  • Webhook 通知(文档更新时推送)
  • 导出 PDF
  • 评论系统

本文档用于指导 Codex 开发,如有疑问请联系范总确认需求。


附录 A:产品概述与目标

A.1 产品定位

DocHub 是面向范总团队(3-5人)的轻量级项目文档管理系统,替代散落在各处的 Markdown 文件和笔记工具,提供统一的文档编写、组织、搜索和分享平台。

A.2 核心目标

目标衡量指标目标值
统一文档管理所有项目文档迁入 DocHub100%
提升查找效率全文搜索命中率>90%
AI 协作AI 自动创建/更新文档成功率>95%
团队可用系统可用时间>99.5%(月)

A.3 成功标准

  • 所有现有项目(ycapi、伴享、Meet5调研等)文档完成迁移
  • 团队日常文档操作全部在 DocHub 完成
  • AI(露露)可通过 API 自主创建和更新项目文档

附录 B:用户角色与权限详细说明

B.1 角色矩阵

操作管理员 (admin)访客 (viewer)AI Token
查看项目列表
创建/编辑/删除项目
查看文档仅分享链接/api/ai/docs GET
创建/编辑文档/api/ai/docs POST
删除文档
管理任务/api/ai/tasks
创建分享链接
全文搜索

B.2 认证方式

角色认证机制存储
管理员用户名 + 密码 → session cookie (dochub.sid)express-session + SQLite
访客分享链接 URL token (/s/:token) + 可选密码shares 表
AIAuthorization: Bearer <AI_API_TOKEN>环境变量

B.3 安全策略

  • 密码使用 bcryptjs (cost=10) 哈希存储
  • Session cookie 设置 httpOnlysecure(HTTPS)、sameSite: strict
  • AI Token 通过环境变量注入,不存储在数据库
  • 分享链接密码同样 bcrypt 哈希存储
  • 分享链接支持过期时间

附录 C:功能需求详细说明

C.1 项目管理

编号功能描述优先级
F-P01创建项目填写名称、描述、图标(emoji)、主题色,自动生成 slugP0
F-P02项目列表卡片式展示,显示文档数、进行中任务数P0
F-P03编辑项目修改名称、描述、图标、主题色、排序P0
F-P04删除项目级联删除所有文档和任务(需确认)P0

C.2 文档管理

编号功能描述优先级
F-D01文档树支持文件夹嵌套、拖拽排序P0
F-D02创建文档选择类型(需求/设计/API/计划/报告/会议/通用),自动创建 .md 文件P0
F-D03创建文件夹组织文档层级结构P0
F-D04Markdown 编辑CodeMirror 6,左右分栏实时预览P0
F-D05Markdown 渲染支持代码高亮、Mermaid 图表、任务列表、数学公式P0
F-D06移动文档修改父级文件夹、调整排序P1
F-D07删除文档同时删除 .md 文件和 FTS 索引P0

C.3 任务看板

编号功能描述优先级
F-T01三列看板待办 / 进行中 / 已完成P0
F-T02创建任务标题、描述、优先级(普通/重要/紧急)、截止日期P0
F-T03拖拽移动跨列拖拽更新状态,列内拖拽调整排序P0
F-T04按状态过滤URL 参数 `?status=tododoing

C.4 搜索

编号功能描述优先级
F-S01全文搜索FTS5 索引,支持标题+内容搜索P0
F-S02项目过滤可限定搜索范围到特定项目P1
F-S03高亮片段搜索结果显示匹配上下文(<mark> 标记)P0

C.5 分享

编号功能描述优先级
F-SH01生成分享链接UUID token,可选密码保护和过期时间P0
F-SH02公开访问页独立渲染页面,无需登录P0
F-SH03访问统计记录 view_countP1
F-SH04撤销分享删除分享记录P0

C.6 AI 写入

编号功能描述优先级
F-AI01创建/更新文档POST /api/ai/docs,upsert 语义P0
F-AI02读取文档GET /api/ai/docs/:project/:docSlugP0
F-AI03创建任务POST /api/ai/tasksP1
F-AI04更新任务状态PATCH /api/ai/tasks/:idP1

附录 D:非功能需求

D.1 性能

指标目标
页面首次加载< 2 秒(Gzip + Vite 构建优化)
API 响应时间< 200ms(P95)
全文搜索响应< 500ms(FTS5 索引)
最大文档数量支持 1000+ 文档
最大单文档大小1MB Markdown
并发用户5-10(小团队场景)

D.2 安全

措施说明
HTTPSCaddy 自动管理 Let's Encrypt 证书
密码哈希bcryptjs,cost factor = 10
Session 安全httpOnly + secure + sameSite
SQL 注入防护全部使用参数化查询(better-sqlite3 prepared statements)
XSS 防护Markdown 渲染使用白名单 HTML 标签
路径穿越防护文件操作限制在 data/ 目录内
AI Token环境变量存储,不暴露在前端

D.3 可用性

指标目标
系统可用性> 99.5%(PM2 自动重启)
数据备份SQLite 单文件 + .md 文件,可直接 cp 或 Git 备份
崩溃恢复PM2 自动重启,SQLite WAL 模式防数据损坏
移动端适配响应式设计,支持主流移动浏览器

D.4 可维护性

  • 单进程架构,PM2 管理,日志集中在 ~/.pm2/logs/
  • SQLite 零运维,无需 DBA
  • 前后端分离构建,前端 npm run build 输出静态文件
  • 代码注释覆盖关键逻辑

附录 E:API 接口文档补充

以下补充 DESIGN.md 第 6 章未覆盖的实现细节,基于实际代码。

E.1 通用约定

  • Base URLhttps://docs.ycapis.com/api
  • Content-Typeapplication/json
  • 认证:Session cookie(管理员)/ Bearer Token(AI)/ URL token(分享)
  • 错误格式{ "error": "错误描述" }

E.2 辅助模块 _helpers.js

实际代码中 routes/_helpers.js 提供以下共享函数,非独立路由:

函数用途
getProjectBySlug(slug)按 slug 查询项目
readDocumentContent(doc)从 .md 文件读取内容
writeDocFile(projectSlug, docSlug, content)写入 .md 文件并返回相对路径
removeDocFile(filePath)删除 .md 文件
renameDocFile(oldPath, newPath)重命名/移动 .md 文件
upsertFts(docId, title, content)更新 FTS5 全文索引
deleteFts(docId)删除 FTS5 索引条目
buildDocTree(docs)将平铺文档列表构建为树形结构
ensureUniqueSlug(projectId, parentId, slug)确保 slug 唯一(自动追加数字后缀)
slugify(input)生成 URL 友好标识

E.3 分享公开访问接口详细

GET /api/shares/public/:token
  查询参数:?password=xxx(或 Header: X-Share-Password)
  
  响应 200:{ doc: { title, slug, project_name, content }, share: { view_count } }
  响应 401:{ error: "Password required", requires_password: true }
  响应 410:{ error: "Share link has expired" }
  响应 404:{ error: "Shared document not found" }

E.4 AI 接口详细

GET /api/ai/docs/:project/:docSlug
  Headers: Authorization: Bearer <AI_API_TOKEN>
  响应 200:{ doc: { id, title, slug, doc_type, content, project_slug } }
  
POST /api/ai/docs
  Headers: Authorization: Bearer <AI_API_TOKEN>
  Body: { project, title, slug?, doc_type?, parent?, content }
  行为:若 project+parent+slug 已存在则更新,否则创建
  响应 200/201:{ ok: true, doc: { id, slug, url } }
  
POST /api/ai/tasks
  Headers: Authorization: Bearer <AI_API_TOKEN>
  Body: { project, title, description?, status?, priority?, due_date? }
  响应 201:{ task: { id, title, status } }

PATCH /api/ai/tasks/:id
  Headers: Authorization: Bearer <AI_API_TOKEN>
  Body: { status?, title?, description?, priority?, due_date? }
  响应 200:{ task: { id, title, status } }

附录 F:数据库 Schema 补充说明

对照实际 server/db.js 代码,补充第 4 章 Schema 的实现差异。

F.1 与设计 Schema 的差异

项目设计文档实际代码
FTS 表定义content=documents, content_rowid=id无 content/content_rowid(独立 FTS 表)
触发器未提及实现了 trg_projects_updatedtrg_documents_updatedtrg_tasks_updated 自动更新 updated_at
种子数据未提及seedAdminUser() 自动创建 admin 用户
外键已定义启用 PRAGMA foreign_keys = ON

F.2 数据库触发器

-- 项目更新时间自动维护
CREATE TRIGGER IF NOT EXISTS trg_projects_updated
AFTER UPDATE ON projects
BEGIN UPDATE projects SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; END;

-- 文档更新时间自动维护
CREATE TRIGGER IF NOT EXISTS trg_documents_updated
AFTER UPDATE ON documents
BEGIN UPDATE documents SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; END;

-- 任务更新时间自动维护
CREATE TRIGGER IF NOT EXISTS trg_tasks_updated
AFTER UPDATE ON tasks
BEGIN UPDATE tasks SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; END;

附录 G:部署架构

G.1 服务器环境

项目
服务器范总自有服务器
OSUbuntu 22.04 LTS
Node.jsv22.x
域名docs.ycapis.com
SSLCaddy 自动 HTTPS (Let's Encrypt)

G.2 部署拓扑

互联网用户 / AI(露露)

        ▼ HTTPS :443
┌──────────────────┐
│  Caddy (反向代理)  │  docs.ycapis.com → localhost:3100
└────────┬─────────┘
         │ HTTP :3100
┌────────▼─────────┐
│  DocHub (PM2)     │  Express + Vue 3 SPA (静态文件)
│  ├─ API Server    │
│  └─ Static Files  │
└──┬──────┬──────┬─┘
   │      │      │
   ▼      ▼      ▼
SQLite  .md文件  FTS5索引
(dochub.db)  (data/projects/*)

G.3 备份策略

# 推荐:每日备份脚本
#!/bin/bash
BACKUP_DIR="/root/backups/dochub/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
cp /root/Projects/doc-system/data/dochub.db "$BACKUP_DIR/"
cp -r /root/Projects/doc-system/data/projects/ "$BACKUP_DIR/"
# 保留最近 30 天
find /root/backups/dochub/ -maxdepth 1 -mtime +30 -exec rm -rf {} \;

G.4 监控

  • PM2pm2 monit 实时监控 CPU/内存
  • 日志pm2 logs dochub 查看应用日志
  • 健康检查:可添加 GET /api/health 端点供外部监控

附录 H:里程碑与排期

基于第 10 章开发计划,细化为里程碑。

里程碑内容预计完成交付物
M1:项目骨架Express + Vue 3 脚手架、SQLite 初始化、认证系统、项目 CRUD第 1 周可登录、可创建项目
M2:文档系统文档 CRUD、文档树、Markdown 渲染(highlight.js + mermaid)第 2 周可创建/编辑/浏览文档
M3:编辑器与看板CodeMirror 6 集成、实时预览、任务看板、拖拽排序第 3 周完整编辑体验 + 任务管理
M4:搜索与分享FTS5 全文搜索、搜索 UI、分享链接、公开页面、AI API第 4 周搜索可用、可分享文档、AI 可写入
M5:部署上线响应式适配、数据迁移、Caddy 配置、PM2 部署、测试第 5 周生产环境可用

验收标准

  • 管理员可登录并管理所有项目和文档
  • Markdown 编辑器支持实时预览、代码高亮、Mermaid 图表
  • 全文搜索可在 500ms 内返回结果
  • 分享链接可正常访问(含密码保护和过期)
  • AI 可通过 Bearer Token 创建和更新文档
  • 移动端浏览器可正常使用
  • 现有项目文档完成迁移

On this page