【FDE知识库】(4):企业知识库怎么选型,开源知识库分享几个,选择开源协议友好的版本,开发wiki-go项目

【FDE知识库专栏】:

https://blog.csdn.net/freewebsys/category_13221845.html

企业内部搭建 Wiki 常用的开源项目 在 GitHub 上有非常多经典、成熟的选择。以下是按技术栈、特点以及开源协议分类的主流开源项目:

这个都是老项目了,可以使用AI转换成go语言实现下。

1. 现代化 / 颜值与性能兼顾

  • Wiki.js
    • 开源协议 :AGPL-3.0
    • 技术栈:Node.js + Vue.js + 数据库(PostgreSQL, MySQL, SQLite 等)
    • 特点:目前 GitHub 上人气极高(星标 28k+)的现代化 Wiki 系统。界面极其美观,支持 Markdown / Visual 编辑器、多数据库、权限管理及与 GitHub/GitLab 自动双向同步。
  • BookStack (现已迁移至 Codeberg,但 GitHub 保留镜像)
    • 开源协议 :MIT
    • 技术栈:PHP (Laravel) + MySQL/MariaDB
    • 特点:采用非常符合直觉的"书(Book)- 章节(Chapter)- 页面(Page)"层级结构,对非技术人员友好,支持所见即所得(WYSIWYG)和 Markdown 编辑器。

https://demo.bookstackapp.com/books/bookstack-demo-site

2. 轻量级 / 国产或轻量自研

  • MM-Wiki
    • 开源协议 :MIT
    • 技术栈:Go (Golang) + MySQL
    • 特点:国人开发、轻量级的企业知识分享与团队协同软件。单二进制文件部署极其简单,支持独立空间、Markdown、LDAP 登录、附件上传及全文检索,非常适合中小团队快速私有化部署。

偏demo,界面比较简陋。

3. 经典老牌 / 高度可定制

  • DokuWiki
    • 开源协议 :GPL-2.0
    • 技术栈 :PHP(基于文本文件,不需要数据库)
    • 特点:老牌轻量级 Wiki,所有页面直接保存在服务器文本中,备份迁移极其方便,运行速度快,适合对性能和简单性要求高的场景。
  • XWiki
    • 开源协议 :LGPL-2.1
    • 技术栈:Java
    • 特点:企业级开源 Wiki 的老大哥,功能极其强大且高度可编程(类似开源版的 Confluence),支持宏、复杂权限、工作流和海量插件,适合大型企业深度定制。

xwiki 的界面展示:

  • MediaWiki (维基百科同款引擎)
    • 开源协议 :GPL-2.0-or-later
    • 技术栈:PHP + 数据库 (MySQL/MariaDB/Postgres)
    • 特点:全球最大规模的 Wiki 引擎,稳定性与扩展性极强,但学习曲线和页面语法(Wikitext)对企业普通日常文档编写可能稍显繁琐。

4. 基于 Git / 文档即代码(Docs-as-Code)

如果你们团队习惯用 Markdown + Git 的工作流,不需要复杂的在线协同数据库,也可以考虑:

5,开源代码wiki-go实现架构设计

1. 目标与范围

Wiki Go 将 BookStack 的核心 Wiki 能力迁移到 Go 技术栈,目标包括:

  • 单进程可运行:GoFrame 同时提供 REST API 和 Vue SPA,无需额外 Web 服务器。
  • 本地优先:SQLite 文件 + 本地文件目录即可完成部署,零外部依赖。
  • 保留 BookStack 心智模型:书架 / 书籍 / 章节 / 页面、角色权限、受限实体、版本、回收站。
  • 可扩展:分层清晰,后续可替换数据库、增加 OIDC/SAML、导入器等。

不在当前范围内:MFA、OIDC/SAML、Webhook、ZIP 导入导出、画板、WYSIWYG 编辑器、主题系统、多语言完整翻译等。

项目代码:

https://gitcode.com/any-to-go/wiki-go

2. 总体架构

复制代码
┌──────────────────────────────────────────────────────────────┐
│                        Browser (Vue 3 SPA)                   │
│  Vue Router · Pinia · Axios · marked/DOMPurify(仅预览)       │
└───────────────────────────┬──────────────────────────────────┘
                            │ HTTP (JSON / multipart)
┌───────────────────────────▼──────────────────────────────────┐
│                     GoFrame HTTP Server                       │
│  CORS → Auth(JWT/Cookie) → Router → Controller                │
│                              │                               │
│                         Service 层                            │
│       权限校验 · 内容 CRUD · 搜索 · 版本 · 回收站 · 上传       │
│                              │                               │
│                      GORM / glebarez SQLite                  │
│                              │                               │
│         data/wiki.db  ·  data/uploads/images|files          │
└──────────────────────────────────────────────────────────────┘

生产模式下,GET:/* 由 controller.Frontend 处理:请求优先命中 go:embed 内嵌的静态资源,非 /api 且不带扩展名的路径回退到内嵌的 index.html,因此二进制运行时不依赖 web/dist 目录。

3. 代码分层

目录 职责
main.go 调用 cmd.Main.Run(gctx.GetInitCtx())
internal/cmd gcmd 命令定义,转调 app.Run
internal/app 装配配置、数据库、服务与 HTTP Server;router.go 注册全部路由
internal/config 从 manifest/config/config.yaml 读取配置并应用环境变量覆盖
internal/dao 打开 SQLite、AutoMigrate、写入权限/角色/设置/管理员/示例内容
internal/model GORM 模型与表名、实体类型常量
internal/middleware 认证上下文 AuthContext、JWT/Cookie 提取、CORS
internal/service 业务规则与权限判断;按领域拆分为多个文件
internal/controller 解析请求参数、调用 service、统一响应;不包含业务规则
internal/response {code, message, data} 响应封装与分页结构
internal/apperr 带 HTTP 状态码的业务错误
internal/pkg Markdown 渲染、JWT、slug 生成
web Vue 前端工程;embed.go 通过 //go:embed all:dist 将构建产物打入二进制

依赖方向:controller → service → model/dao,middleware 被 controller 和 service 使用;service 不依赖 controller。

4. 请求生命周期

  1. GoFrame 命中路由,执行分组中间件:
    • 公共组:CORS(健康检查、系统状态、公共设置、登录)
    • 受保护组:CORS → Auth
  2. Auth 依次从 Authorization: Bearer 或 HttpOnly Cookie wiki_token 读取 JWT。
  3. 校验 JWT(HS256,claim uid),加载用户、角色与权限集合,写入 r.SetCtxVar("wiki.auth", *AuthContext)。
  4. Controller 通过 h.auth(r) 获取上下文,解析参数(r.Parse、GetRouter、表单/上传文件)。
  5. Service 执行权限校验和业务逻辑,返回领域对象或 *apperr.Error。
  6. Controller 用 response.Data/List 输出统一 envelope。
  7. 出错时 response.Err 映射业务错误到 HTTP 状态码(400/401/403/404/409/500)。

认证细节

  • 登录返回 JWT,同时写入 HttpOnly、SameSite=Lax 的 Cookie,便于 <img>、下载链接等浏览器直接发起的请求鉴权。
  • 前端 Axios 额外通过 Authorization 头发送令牌。
  • 权限在每次请求时从数据库重新加载,角色变更立即生效。
  • admin 系统角色短路所有权限检查。

5. 权限模型

5.1 角色与权限

  • 用户通过 user_roles 关联多个角色。
  • 角色通过 role_permissions 关联权限。
  • 权限命名:<entity>-<action>-<scope>,例如 page-update-all、bookshelf-view-own。
  • all 表示对任意对象生效;own 仅对 owned_by = 当前用户 的实体生效。

内容实体权限:书架、书籍、章节、页面 × view/create/update/delete × all/own。

系统权限:users-manage、settings-manage、restrictions-manage-all/own、content-export 等。

功能权限:附件、评论、图片的 create/update/delete(all/own)。

5.2 可见性继承

CanViewEntity 不只检查实体自身,还递归检查上级:

  • 页面:检查自身 → 章节(若有)→ 书籍(若有)
  • 章节:检查自身 → 书籍
  • 书籍 / 书架:检查自身

因此书籍被设为受限时,其下页面自动不可见。

5.3 受限实体

实体的 restricted = true 时:

  • 不再使用角色级 all/own 判断;
  • 改为查询 entity_permissions(entity_type, entity_id, role_id, action);
  • 拥有对应角色授权的用户才可执行该动作。

/api/:type/:id/permissions 用于读取/更新实体级授权;仅 restrictions-manage-all 或实体拥有者 + restrictions-manage-own 可操作。

5.4 创建子内容

创建页面/章节时,服务层要求:

  1. 能查看父实体;
  2. 拥有 childType-create-all,或拥有父实体且具备 childType-create-own。

6. 内容模型

采用 BookStack 式单表多态 设计:entities 表通过 type 区分 bookshelf、book、chapter、page。

  • 书籍通过 bookshelf_books 与书架建立有序多对多关系。
  • 章节通过 book_id 归属书籍;页面通过 book_id/chapter_id 归属书籍与可选章节。
  • 页面正文同时保存 Markdown、渲染后的 HTML 与纯文本,搜索使用 text,展示使用 html,编辑使用 markdown。
  • 软删除使用 GORM DeletedAt,回收站查询使用 Unscoped()。
  • 页面版本在 page_revisions 中保存快照,超过配置上限时清理最旧版本。

7. 数据一致性

  • 创建/更新实体时同步维护 updated_by、updated_at、revision_count、标签与活动日志。
  • 删除书籍/章节/页面时级联软删除其子实体,并记录 deleted_by。
  • 恢复时校验父实体是否仍处于活跃状态(针对页面)。
  • 彻底删除时按类型清理版本、评论、附件与图片文件。
  • 实体级权限更新使用事务:先清空该实体授权,再按 restricted 重建。

8. 搜索

  • 普通搜索:name / description / markdown / text 的 LIKE 匹配。
  • 标签搜索:[name=value] 形式,匹配 tags 表。
  • 结果统一经过 CanViewEntity 过滤,避免越权泄露。
  • 摘要使用纯文本截断,返回 type/title/snippet/url。

9. 上传与静态资源

  • 图片:仅允许 png/jpg/jpeg/gif/webp/bmp,保存到 data/uploads/images,记录 MIME 与大小。
  • 附件:保存到 data/uploads/files/{pageID},支持外链附件。
  • 大小限制来自 wiki.upload.maxSizeMb,同时设置 GoFrame 请求体上限。
  • 图片通过 GET /api/images/:id/file 内联输出;附件通过 /download 下载或 302 跳转外链。
  • 由于登录写入 Cookie,<img src> 与下载链接可直接通过浏览器鉴权。
  • 前端静态资源:web/dist 经 web/embed.go 嵌入二进制,由 controller.Frontend 通过 fs.FS 读取;assets/* 使用 immutable 缓存,index.html 使用 no-cache。详见 前端内嵌。

10. 错误与响应

统一响应:

json 复制代码
{ "code": 0, "message": "ok", "data": { } }

失败时 code 为 HTTP 状态码,message 为面向用户的中文提示:

状态 典型场景
400 参数缺失、类型不匹配、业务校验失败
401 未登录、令牌失效
403 权限不足
404 内容不存在、接口不存在
409 邮箱/角色名重复
500 未预期的数据库或系统错误

11. 与 BookStack 的结构对应

BookStack Wiki Go
Laravel Controller + Routes controller/ + app/router.go
Service/Repos service/
Eloquent Entity/Page/Book/Chapter 单表 model.Entity
restrictions 表 entity_permissions
role_user user_roles
permission_role role_permissions
Blade 视图 Vue 页面与组件
中间件 auth middleware.Auth
activity 日志 activities 表 + logActivity
上传目录 data/uploads

12. 扩展点与限制

可扩展点:

  • 在 router.go 增加路由与 controller 方法即可接入新功能。
  • Service 构造依赖 *gorm.DB 与 *config.Config,便于替换存储或注入测试库。
  • 权限判断集中在 service/permission.go,新增动作只需补充权限定义与判断。
  • 前端页面按路由懒加载,新增模块只需增加路由与页面组件。

当前限制:

  • 所有内容接口要求登录(app-public 仅作为预留设置)。
  • 无实时协作、无 Webhook、无 MFA/OIDC/SAML。
  • 搜索为 SQLite LIKE,数据量大时建议替换为 FTS5。
  • 回收站保留天数仅存设置,自动清理任务尚未实现。
  • 导入器(BookStack/ZIP)尚未实现。
相关推荐
分布式存储与RustFS2 小时前
JuiceFS 接 RustFS 当数据后端:把对象存储挂成本地文件系统
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
unconditional3 小时前
我拆了 sdkm 的自定义 SDK 机制:所谓“内置”,就是官方提前帮你填好的表
rust·开源
福大大架构师每日一题3 小时前
excelize v2.11.1发布:Go 1.26.0起步,16项安全修复与嵌入对象能力全面升级
开发语言·安全·golang
miofly4 小时前
GitHub 今日推荐|auto-ontology:给 Agent 装上企业数据的语义索引
python·开源·github
小小龙学IT4 小时前
Go 语言 pprof 性能剖析与调优深度解析:把“卡在哪“变成一张可执行的数据图
开发语言·后端·golang
狂师5 小时前
我开发了一款免费开源的测试开发刷题学习网站
面试·开源·测试
十二同学啊5 小时前
Go 工程化详解:项目结构、代码规范、测试体系与 CI/CD 实践
ci/cd·golang·代码规范
CServer_016 小时前
开源!汽车零部件仓储的数字孪生协同方案
物联网·开源·汽车·制造
分布式存储与RustFS6 小时前
K8s 集群备份落到自建对象存储:Velero 接 RustFS 配置指南
运维·云原生·开源·对象存储·分布式存储·s3·性能基准