logo
0
1
WeChat Login
docs: 重构文档目录结构并更新README

M-Doc 企业级文档管理系统

Go Version Gin Framework GORM

M-Doc 是一个功能强大的企业级文档管理系统,支持组织管理、文档版本控制、多人协作、权限管理和智能搜索。基于 Go + Gin + GORM 构建的高性能 RESTful API 后端,配合 Nuxt 3 前端,为团队提供优雅的文档协作体验。

✨ 核心特性

文档管理

  • 📚 分层文档结构 - 支持文档树形组织,层级清晰
  • 📝 Markdown 编辑 - 强大的 Markdown 编辑器,实时预览
  • 🔄 Git 风格版本控制 - 完整的版本历史、分支、合并和回退
  • 🌿 版本分支管理 - Fork 版本、版本对比、冲突检测
  • 🔍 AI 向量搜索 - 基于 Qdrant 的智能语义搜索

组织协作

  • 🏢 多租户组织 - 支持多组织管理,组织间数据隔离
  • 👥 团队协作 - 组织成员管理,支持多角色权限控制
  • 🔐 细粒度权限 - Owner、Admin、Member、Guest 四级角色
  • 🔗 文档分享 - 支持文档公开分享,可设置访问密码
  • 👁️ 访客追踪 - 基于 UUID 的访客标识和访问控制

用户认证

  • 🔑 JWT 认证 - 安全的 Token 认证机制
  • 🌐 OIDC 集成 - 支持第三方 SSO 登录(Google、Azure AD 等)
  • 🔒 密码加密 - 使用 bcrypt 加密存储
  • 📸 头像上传 - 支持用户头像自定义

企业级功能

  • 🚀 高性能架构 - 基于 Gin 的高并发处理能力
  • 💾 多数据库支持 - MySQL、PostgreSQL、SQLite
  • 🗄️ Redis 缓存 - 权限缓存、会话管理
  • ☁️ S3 对象存储 - 支持 AWS S3、MinIO 等
  • 📊 健康检查 - 完整的服务健康监控
  • 🔧 配置热重载 - 支持 SIGHUP 信号重载配置
  • 🛡️ XSS 防护 - Markdown 渲染时自动清理恶意代码
  • 📅 定时任务 - 基于 Cron 的后台任务调度

📞 加群获取帮助

QQ企业微信
wechat_qr_code.pngwechat_qr_code.png
QQ群:1021660914
点击链接加入群聊【木雷坞开源家】
扫描上方二维码加入微信群

🚀 快速开始

环境要求

  • Go: 1.25.0 或更高版本
  • Node.js: 18+ (前端开发)
  • pnpm: 最新版本 (前端包管理)
  • 数据库: MySQL 5.7+、PostgreSQL 12+ 或 SQLite 3
  • Redis: 6.0+ (推荐)

1. 克隆项目

git clone https://cnb.cool/mliev/mdoc/mdoc-server cd mdoc-server # 初始化前端子模块 git submodule update --init --recursive

2. 配置环境

# 复制配置文件 cp config.yaml.example config.yaml # 编辑配置文件,配置数据库、Redis 等 vim config.yaml

3. 安装依赖

# 后端依赖 go mod tidy # 前端依赖(可选,如果需要本地开发前端) cd frontend pnpm install cd ..

4. 初始化数据库

应用启动时会自动执行数据库迁移,创建所需表结构。

5. 启动服务

后端服务:

# 启动后端 API(监听 http://localhost:8080) go run main.go

前端服务(可选,用于开发):

# 在新终端启动前端开发服务器(监听 http://localhost:3000) cd frontend pnpm dev

6. 访问应用

📁 项目结构

mdoc-server/ ├── main.go # 程序入口 ├── go.mod # Go 模块定义 ├── config.yaml.example # 配置文件示例 ├── config.yaml # 实际配置文件(不提交) ├── CLAUDE.md # Claude Code 开发指南 ├── LICENSE # MIT 许可证 │ ├── app/ # 应用核心代码 │ ├── controller/ # 控制器层(HTTP 请求处理) │ │ ├── auth_controller.go # 用户认证 │ │ ├── oidc_controller.go # OIDC 认证 │ │ ├── organization_controller.go # 组织管理 │ │ ├── document_controller.go # 文档管理 │ │ ├── version_controller.go # 版本管理 │ │ ├── article_controller.go # 文章管理 │ │ ├── share_controller.go # 分享功能 │ │ ├── upload_controller.go # 文件上传 │ │ └── user_controller.go # 用户管理 │ │ │ ├── service/ # 服务层(业务逻辑) │ │ ├── auth_service.go │ │ ├── oidc_service.go │ │ ├── organization_service.go │ │ ├── document_service.go │ │ ├── version_service.go │ │ ├── article_service.go │ │ ├── permission_service.go # 权限控制 │ │ ├── permission_cache_service.go # 权限缓存 │ │ ├── share_service.go │ │ └── upload_service.go │ │ │ ├── dao/ # 数据访问层 │ │ ├── user_dao.go │ │ ├── organization_dao.go │ │ ├── document_dao.go │ │ ├── version_dao.go │ │ ├── article_dao.go │ │ └── document_share_dao.go │ │ │ ├── model/ # 数据模型(GORM) │ │ ├── user.go # 用户模型 │ │ ├── organization.go # 组织模型 │ │ ├── document.go # 文档模型 │ │ ├── document_version.go # 文档版本 │ │ ├── article.go # 文章实体 │ │ ├── article_version.go # 文章版本快照 │ │ ├── document_version_article.go # 版本-文章关联 │ │ └── document_share.go # 文档分享 │ │ │ ├── dto/ # 数据传输对象 │ │ ├── auth_dto.go │ │ ├── organization_dto.go │ │ ├── document_dto.go │ │ ├── article_dto.go │ │ ├── version_dto.go │ │ └── share_dto.go │ │ │ ├── middleware/ # 中间件 │ │ ├── auth_middleware.go # JWT 认证 │ │ ├── cors_middleware.go # CORS 处理 │ │ └── uuid_middleware.go # 访客 UUID │ │ │ ├── listener/ # 事件监听器 │ │ ├── article_logger_listener.go │ │ ├── document_logger_listener.go │ │ └── vectorize_listener.go # AI 向量化 │ │ │ ├── cron/ # 定时任务 │ │ └── orphan_article_cleaner.go # 孤立文章清理 │ │ │ └── constants/ # 常量定义 │ └── reserved_slugs.go │ ├── cmd/ # 命令行入口 │ ├── run.go # 启动逻辑 │ └── start.go # Start 函数(可被企业版扩展) │ ├── config/ # 配置管理 │ ├── assembly.go # 依赖注入配置 │ ├── server.go # 服务器配置 │ └── autoload/ # 自动加载配置 │ ├── base.go │ ├── database.go # 数据库配置 │ ├── redis.go # Redis 配置 │ ├── router.go # 路由配置 │ ├── middleware.go # 中间件配置 │ ├── s3.go # S3 配置 │ ├── migration.go # 数据库迁移 │ └── vectorstore.go # 向量数据库 │ ├── pkg/ # 公共包(可被企业版导入) │ ├── helper/ # 辅助函数 │ ├── interfaces/ # 接口定义 │ └── service/ # 服务实现 │ ├── auth/ # JWT 工具 │ ├── base62/ # Base62 编码 │ ├── cache/ # 缓存服务 │ ├── commit/ # Git 风格提交 │ ├── config/ # 配置服务 │ ├── cron/ # 定时任务 │ ├── database/ # 数据库服务 │ ├── env/ # 环境变量 │ ├── event/ # 事件系统 │ ├── http_server/ # HTTP 服务器 │ ├── logger/ # 日志服务 │ ├── markdown/ # Markdown 渲染 │ ├── migration/ # 数据库迁移 │ ├── redis/ # Redis 服务 │ ├── reload/ # 配置重载 │ ├── vectorize/ # 向量化服务 │ └── vectorstore/ # 向量存储(Qdrant/pgvector) │ ├── frontend/ # 前端子模块(Git 子模块) │ ├── pages/ # Nuxt 页面 │ ├── components/ # Vue 组件 │ ├── composables/ # 组合式 API │ ├── stores/ # Pinia 状态管理 │ ├── services/ # API 服务层 │ ├── middleware/ # 路由中间件 │ ├── types/ # TypeScript 类型 │ └── nuxt.config.ts # Nuxt 配置 │ ├── migrations/ # 数据库迁移文件 ├── tests/ # 测试文件 ├── examples/ # 示例代码 ├── docs/ # 文档 ├── templates/ # 模板文件 └── public/ # 静态资源

🛠️ 技术栈

后端技术

技术版本描述
Go1.25.0编程语言
Gin1.11.0Web 框架
GORM1.31.1ORM 框架
MySQL/PostgreSQL/SQLite-关系型数据库
Redis-缓存和会话存储
Qdrant-向量数据库(AI 搜索)
Viper1.21.0配置管理
Zap1.27.1结构化日志
JWT5.3.1JSON Web Tokens
AWS SDKv2S3 对象存储
LangChain Go0.1.14AI 集成
Gomarkdown-Markdown 解析
Bluemonday1.0.27XSS 防护

前端技术(Git 子模块)

技术版本描述
Nuxt 33.20.2Vue.js 框架 + SSR
Vue 3-渐进式前端框架
TypeScript-类型安全
Pinia-状态管理
shadcn-vue-UI 组件库
Tailwind CSS-样式框架
Monaco Editor-代码编辑器
MD Editor v3-Markdown 编辑器
Mermaid-图表渲染
Prism.js-代码高亮

🏗️ 架构设计

分层架构

┌─────────────────────────────────┐ │ HTTP Layer │ │ (Gin Router & Middleware) │ ├─────────────────────────────────┤ │ Controller Layer │ │ (Request/Response Handling) │ ├─────────────────────────────────┤ │ Service Layer │ │ (Business Logic) │ ├─────────────────────────────────┤ │ DAO Layer │ │ (Data Access Objects) │ ├─────────────────────────────────┤ │ Model Layer │ │ (Database Models) │ └─────────────────────────────────┘

依赖注入(Assembly 模式)

项目采用 Assembly 模式实现依赖注入,组件按顺序初始化:

// 初始化顺序在 config/assembly.go 中定义 envAssembly.Env{} // 环境变量 configAssembly.Config{} // 配置加载 loggerAssembly.Logger{} // 日志系统 databaseAssembly.Database{} // 数据库 redisAssembly.Redis{} // Redis cacheAssembly.Cache{} // 缓存层

通过 helper.GetDatabase(), helper.GetConfig() 等方法访问共享依赖。

数据模型关系

User (用户) ├─> UserOrganization (用户-组织关联) │ └─> Organization (组织) │ └─> Document (文档) │ ├─> DocumentVersion (文档版本) │ │ └─> DocumentVersionArticle (版本-文章关联) │ │ └─> Article (文章实体) │ │ └─> ArticleVersion (文章版本快照) │ └─> DocumentShare (文档分享)

文档版本系统

  • Document: 文档容器,属于某个组织
  • DocumentVersion: 文档的版本(master/分支),支持 fork 和 diff
  • Article: 文章逻辑实体,使用 stable_key 在版本间保持身份
  • ArticleVersion: 文章内容快照,每次编辑创建新快照
  • DocumentVersionArticle: 版本-文章关联,定义文章在版本中的层次结构和排序

权限控制

组织级别角色:

  • Owner: 组织所有者,完全控制权限
  • Admin: 管理员,可管理成员和文档
  • Member: 成员,可编辑组织文档
  • Guest: 访客,只读权限

文档可见性:

  • Public: 公开可见
  • Org: 组织内可见
  • Private: 私有(仅创建者)

📋 API 接口

认证接口

# 用户注册 POST /api/auth/register # 用户登录 POST /api/auth/login # 获取当前用户信息 GET /api/auth/me # 更新个人资料 PUT /api/auth/profile # 修改密码 POST /api/auth/change-password # 上传头像 POST /api/auth/avatar # OIDC 授权 GET /api/auth/oidc/authorize # OIDC 回调 POST /api/auth/oidc/callback

组织接口

# 列出组织 GET /api/organizations # 获取组织详情 GET /api/organizations/:orgSlug # 创建组织 POST /api/organizations # 更新组织 PUT /api/organizations/:orgSlug # 删除组织 DELETE /api/organizations/:orgSlug # 转让组织所有权 POST /api/organizations/:orgSlug/transfer # 添加成员 POST /api/organizations/:orgSlug/members # 更新成员角色 PUT /api/organizations/:orgSlug/members/:userId # 移除成员 DELETE /api/organizations/:orgSlug/members/:userId

文档接口

# 列出文档 GET /api/documents GET /api/organizations/:orgSlug/documents # 获取文档详情 GET /api/organizations/:orgSlug/documents/:docSlug # 创建文档 POST /api/organizations/:orgSlug/documents # 更新文档 PUT /api/documents/:id # 删除文档 DELETE /api/documents/:id

版本接口

# 创建版本 POST /api/organizations/:orgSlug/documents/:docSlug/versions # Fork 版本 POST /api/versions/:id/fork # 版本对比 GET /api/diff/versions/:v1/:v2

文章接口

# 创建文章 POST /api/versions/:id/articles # 更新文章 PUT /api/versions/:id/articles/:articleId # 删除文章 DELETE /api/versions/:id/articles/:articleId # 发布文章 POST /api/versions/:id/articles/:articleId/publish # 合并文章 POST /api/versions/:id/articles/merge # 检查合并冲突 GET /api/versions/:id/articles/:articleId/merge-conflict # 强制合并 POST /api/versions/:id/articles/:articleId/force-merge # 回退版本 POST /api/versions/:id/articles/:articleId/revert

分享接口

# 创建分享链接 POST /api/organizations/:orgSlug/documents/:docSlug/share # 获取分享详情 GET /api/share/:shareId # 验证分享密码 POST /api/share/:shareId/verify

文件上传

# 上传文件(支持图片等) POST /api/upload

健康检查

# 完整健康检查 GET /health # 简单健康检查 GET /health/simple

响应示例:

{ "code": 200, "message": "健康检查成功", "data": { "status": "UP", "timestamp": 1703123456, "services": { "database": { "status": "UP" }, "redis": { "status": "UP" } } } }

⚙️ 配置说明

核心配置 (config.yaml)

# 服务器配置 server: mode: release # debug, release, test addr: ":8080" # HTTP 服务配置 http: load_static: false static_mode: embed # disk 或 embed static_dir: [] # 数据库配置(MySQL 示例) database: halt_on_migration_failure: true host: localhost port: 3306 username: root password: password database: mdoc_db charset: utf8mb4 parse_time: true loc: Local max_idle_conns: 10 max_open_conns: 100 conn_max_lifetime: 3600 # PostgreSQL 配置(可选) # postgres: # host: localhost # port: 5432 # username: postgres # password: password # database: mdoc_db # sslmode: disable # Redis 配置 redis: host: localhost port: 6379 password: "" db: 0 pool_size: 10 min_idle_conns: 5 # JWT 配置 jwt: secret: your-secret-key-change-this-in-production expire_hours: 24 # OIDC 配置(可选) oidc: enabled: false issuer: "https://your-oidc-provider.com" client_id: "your-client-id" client_secret: "your-client-secret" redirect_uri: "http://localhost:3000/auth/callback" scopes: - openid - profile - email # CORS 配置 cors: allow_origins: - "*" allow_methods: - "GET" - "POST" - "PUT" - "DELETE" - "OPTIONS" allow_headers: - "Origin" - "Content-Type" - "Authorization"

S3 配置(文件上传)

config.yaml 中添加:

s3: endpoint: "https://s3.amazonaws.com" # 或 MinIO 地址 region: "us-east-1" access_key_id: "your-access-key" secret_access_key: "your-secret-key" bucket: "mdoc-uploads" use_path_style: false # MinIO 设置为 true

向量数据库配置(AI 搜索)

config.yaml 中添加:

vectorstore: type: qdrant # 目前仅支持 qdrant qdrant: url: "http://localhost:6333" api_key: "" # 可选 collection_name: "mdoc_articles"

日志配置

log: level: info # debug, info, warn, error filename: logs/app.log max_size: 100 # MB max_age: 30 # days max_backups: 10 compress: true

🔧 开发指南

本地开发

后端开发:

# 安装依赖 go mod tidy # 运行应用 go run main.go # 或使用 Air 实现热重载(需要安装 Air) air

前端开发:

cd frontend # 安装依赖 pnpm install # 启动开发服务器 pnpm dev # 配置后端 API 地址(创建 .env.local) echo "NUXT_PUBLIC_API_BASE=http://localhost:8080" > .env.local

数据库操作

使用 DAO 层封装数据库操作:

// 示例:通过 DAO 查询用户 import "cnb.cool/mliev/mdoc/mdoc-server/app/dao" func SomeService() error { user, err := dao.GetUserByEmail("user@example.com") if err != nil { return err } // 使用 user... }

使用 helper.GetDatabase() 进行自定义查询:

import "cnb.cool/mliev/mdoc/mdoc-server/internal/helper" func CustomQuery() error { db := helper.GetHelper().GetDatabase() var results []Model return db.Where("status = ?", "active").Find(&results).Error }

添加新的 API 端点

  1. 创建 Controllerapp/controller/):
type MyController struct{} func (c MyController) SomeMethod(ctx *gin.Context) dto.Response { // 业务逻辑 return dto.Response{ Code: 200, Message: "成功", Data: data, } }
  1. 注册路由config/autoload/router.go):
authApi.GET("/my-endpoint", deps.WrapHandler(controller.MyController{}.SomeMethod))

添加新的数据模型

  1. 创建 Modelapp/model/):
type MyModel struct { ID int64 `gorm:"primarykey" json:"id"` Name string `gorm:"size:100;not null" json:"name"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` } func (MyModel) TableName() string { return "my_models" }
  1. 注册到迁移config/autoload/migration.go):
func (receiver Migration) Get() []any { return []any{ &model.MyModel{}, // ...其他模型 } }

代码规范

  • 使用 gofmtgo fmt 格式化代码
  • 遵循 Go 官方命名规范
  • 导出函数和类型必须添加注释
  • 使用 go vet 进行静态检查
  • 控制器方法返回 dto.Response 结构体

🚀 生产部署

Docker 部署

构建镜像:

docker build -t mdoc-server:latest .

运行容器:

docker run -d \ -p 8080:8080 \ -v $(pwd)/config.yaml:/app/config.yaml \ --name mdoc-server \ mdoc-server:latest

Docker Compose(推荐)

创建 docker-compose.yml:

version: '3.8' services: mdoc-server: build: . ports: - "8080:8080" volumes: - ./config.yaml:/app/config.yaml - ./logs:/app/logs depends_on: - mysql - redis environment: - GIN_MODE=release mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: mdoc_db volumes: - mysql_data:/var/lib/mysql ports: - "3306:3306" redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data volumes: mysql_data: redis_data:

启动服务:

docker-compose up -d

手动部署

# 编译 go build -o mdoc-server main.go # 运行 ./mdoc-server # 或使用 systemd 管理服务 sudo cp mdoc-server /usr/local/bin/ sudo systemctl start mdoc-server sudo systemctl enable mdoc-server

环境变量

支持通过环境变量覆盖配置文件:

export SERVER_ADDR=":8080" export DB_HOST=localhost export DB_PORT=3306 export DB_USERNAME=root export DB_PASSWORD=password export DB_DATABASE=mdoc_db export REDIS_HOST=localhost export REDIS_PORT=6379 export JWT_SECRET=your-secret-key

🔨 运维管理

配置热重载

无需重启服务即可重载配置(不会中断连接):

# 发送 SIGHUP 信号 kill -HUP <pid> # 或使用 systemctl(如果使用 systemd) sudo systemctl reload mdoc-server

优雅关闭

服务支持优雅关闭,确保正在处理的请求完成:

# 发送 SIGTERM 或 SIGINT kill -TERM <pid> # 或 Ctrl+C

健康检查

# 完整健康检查(包括数据库、Redis) curl http://localhost:8080/health # 简单健康检查 curl http://localhost:8080/health/simple

日志管理

日志存储在 logs/app.log,使用 Zap 进行结构化记录:

// 记录结构化日志 helper.Logger().Info("用户创建成功", zap.String("email", email), zap.Int64("user_id", userID), )

定时任务

定时任务在 app/cron/ 中定义,由 Cron 服务自动调度:

// 示例:孤立文章清理任务 // 每天凌晨 2 点执行 @daily func CleanOrphanArticles() { // 清理逻辑... }

🌍 前后端集成

API 调用规范

请求头:

  • Authorization: Bearer <token> - JWT 认证(已登录用户)
  • X-Visitor-UUID: <uuid> - 访客标识(分享链接访问)

响应格式:

{ "code": 200, "message": "成功", "data": { ... } }

前端开发配置

frontend/.env.local 中配置后端地址:

NUXT_PUBLIC_API_BASE=http://localhost:8080

API 调用示例(前端)

// 使用 composable const { apiFetch } = useApi() const data = await apiFetch('/api/documents') // 使用便捷方法 import { useApiGet, useApiPost } from '~/composables/useApi' const docs = await useApiGet('/api/documents') await useApiPost('/api/documents', { title: 'New Doc' }) // 使用 service 层 import { documentService } from '~/services' const docs = await documentService.list()

❓ 常见问题

Q: 如何添加新的 OIDC 提供商?

A: 在 config.yaml 中配置 OIDC 参数:

oidc: enabled: true issuer: "https://accounts.google.com" # Google client_id: "your-client-id" client_secret: "your-client-secret" redirect_uri: "http://localhost:3000/auth/callback"

Q: 如何更换数据库驱动?

A: 修改 config.yaml 中的数据库配置,使用对应的数据库配置节:

  • MySQL: 使用 database: 配置
  • PostgreSQL: 使用 postgres: 配置
  • SQLite: 使用 sqlite: 配置

Q: 前端子模块未初始化怎么办?

A: 执行以下命令:

git submodule update --init --recursive cd frontend git fetch git checkout main

Q: 如何启用 AI 向量搜索?

A: 需要配置向量数据库:

  1. 启动 Qdrant 服务
  2. config.yaml 中配置:
vectorstore: type: qdrant qdrant: url: "http://localhost:6333" collection_name: "mdoc_articles"

Q: 数据库迁移如何工作?

A: 项目启动时会自动执行 AutoMigrate(),根据 Model 定义创建或更新表结构。如需手动控制,可修改 config.yaml 中的 halt_on_migration_failure 配置。

Q: 如何配置 S3 文件存储?

A: 在 config.yaml 中添加 S3 配置(支持 AWS S3、MinIO 等兼容服务):

s3: endpoint: "https://s3.amazonaws.com" region: "us-east-1" access_key_id: "your-access-key" secret_access_key: "your-secret-key" bucket: "mdoc-uploads"

📝 开发规范

详细的开发规范请参考 CLAUDE.md,包括:

  • 项目概述和架构设计
  • 开发命令和工作流
  • API 路由规范
  • 前后端集成指南
  • 企业版扩展说明

🤝 贡献指南

欢迎贡献代码、报告问题或提出建议!

  1. Fork 本项目
  2. 创建功能分支:git checkout -b feature/AmazingFeature
  3. 提交更改:git commit -m 'Add some AmazingFeature'
  4. 推送到分支:git push origin feature/AmazingFeature
  5. 提交 Pull Request

开发规范

  • 遵循项目现有的代码风格
  • 添加必要的测试
  • 更新相关文档
  • 确保所有测试通过
  • 提交信息遵循 Conventional Commits 规范

🗺️ 路线图

  • 完善 API 文档(Swagger/OpenAPI)
  • 添加单元测试和集成测试
  • 支持更多向量数据库(Milvus、Weaviate)
  • 支持更多 OIDC 提供商(GitHub、GitLab)
  • 文档导入导出(Word、PDF、Confluence)
  • 多语言支持(i18n)
  • 实时协作编辑(WebSocket)
  • 文档评论和讨论功能
  • 高级权限管理(细粒度权限)
  • 审计日志和操作历史

📄 许可证

本项目可以二次开发用于商业用途,但是禁止发布衍生版本。具体见 授权协议


🔗 相关链接


Copyright © 2024-present, cnb.cool

如有任何问题或需要帮助,欢迎通过上方联系方式加入社区!