# MoKeeText 项目文档 ## 概述 **MoKeeText** 是一个 Web 端富文本笔记管理应用,同时具备网站账号密码管理功能,集成 Mokee Gateway 统一登录网关。 ### 核心功能 | 模块 | 功能 | |------|------| | 📝 **笔记编辑** | 基于 Tiptap 的增强型富文本编辑器,支持文字颜色、图片粘贴/拖拽上传、表格、代码高亮、任务列表 | | 🔐 **网站管理** | 按文件夹分类管理网站及其登录账号密码 | | 🔗 **分享链接** | 笔记可生成分享链接,支持 7天/30天/1年/永久 四种有效期 | | 📥 **智能导入** | 自动解析粘贴的网站账号信息,一键导入 | | 🖼️ **图片上传** | 粘贴/拖拽图片自动上传,存数据库 LONGBLOB,点击全屏预览 | | 👤 **统一登录** | 接入 Mokee Gateway,通过网关转发用户身份,支持 API 级数据隔离 | --- ## 技术栈 | 层 | 技术 | 版本 | |----|------|------| | 后端框架 | FastAPI (Python) | ≥0.115 | | 服务器 | Uvicorn | ≥0.30 | | ORM | SQLAlchemy | ≥2.0 | | 数据库 | MySQL | 8.0 | | 前端框架 | Vue 3 + Vite | 3.5 / 8.x | | 路由 | Vue Router | 4.6 | | 编辑器 | Tiptap | 3.27 | | 代码高亮 | highlight.js (lowlight) | - | | HTTP 客户端 | Axios(生产)/ fetch(本地开发) | 1.18 | | 容器化 | Docker + Docker Compose | - | | Web 服务器 | Nginx (Alpine) | - | --- ## 项目结构 ``` mokeeText/ ├── backend/ # 后端 — FastAPI 应用 │ ├── app.py # 入口:CORS、中间件、路由注册 │ ├── models.py # SQLAlchemy 数据模型(6 张表) │ ├── config.py # 数据库连接配置(环境变量) │ ├── logger.py # 日志系统(按天轮转,保留 30 天) │ ├── init_db.py # 建表脚本 │ ├── requirements.txt # Python 依赖 │ ├── Dockerfile # 后端 Docker 镜像 │ ├── .dockerignore │ ├── routes/ # API 路由 │ │ ├── notes.py # 笔记 CRUD + 分享 + 移动 │ │ ├── websites.py # 网站/账号/文件夹 CRUD + 排序 │ │ ├── import_api.py # 智能导入解析 │ │ ├── upload.py # 图片上传/读取 │ │ └── share.py # 公开分享查看页 │ └── middleware/ │ └── user_context.py # 网关用户上下文中间件 │ ├── frontend/ # 前端 — Vue 3 SPA │ ├── index.html # Vite 入口 HTML │ ├── package.json # 前端依赖 │ ├── vite.config.js # Vite 构建配置 │ ├── nginx.conf # Nginx 配置 │ ├── Dockerfile.frontend # 前端 Nginx Docker 镜像 │ ├── .dockerignore │ ├── .env / .env.production # 环境变量 │ ├── src/ │ │ ├── main.js # Vue 入口 → 挂载 Router + v-permission │ │ ├── App.vue # 根组件:左导航 + 顶栏 + UserChip + 底栏 │ │ ├── router.js # Vue Router 配置 + 路由守卫 │ │ ├── utils/request.js # Axios 实例 + 拦截器 │ │ ├── composables/useApi.js # 双模式 API(dev fetch / prod axios) │ │ ├── directives/permission.js # v-permission 按钮权限指令 │ │ ├── views/ │ │ │ ├── NotesView.vue # 笔记:文件夹侧边栏 + 列表 + 编辑器 │ │ │ ├── WebsitesView.vue # 网站管理:列表 + CRUD 弹窗 │ │ │ └── SharesView.vue # 分享管理 │ │ └── components/ │ │ ├── NoteEditor.vue # Tiptap 增强编辑器 │ │ ├── Modal.vue # 通用弹窗组件 │ │ ├── ConfirmModal.vue │ │ └── PromptModal.vue │ └── static/ │ ├── dist/ # Vite 构建产物(Nginx 托管) │ ├── js/vendor/ # Tiptap UMD 扩展文件 │ ├── css/ │ └── uploads/ │ ├── deploy/ # 部署 │ ├── docker-compose.yml # 双容器编排 │ ├── deploy.py # 日常部署脚本 │ └── migrate_server.py # 服务器迁移脚本(一次性) │ ├── docs/ # 文档 │ ├── README.md # 本文档 │ ├── DEPLOY.md # 部署文档 │ └── superpowers/ # 设计规范 + 实施计划 │ └── memory/ # 会话记忆 ``` --- ## 数据库设计 ### ER 图 ``` folders ──┬── notes ──┬── note_tags ── tags │ └── websites ── accounts uploads(独立,图片存 DB) ``` ### 表结构 #### folders — 文件夹(笔记和网站共用) | 字段 | 类型 | 说明 | |------|------|------| | id | INT PK | 自增主键 | | name | VARCHAR(100) | 文件夹名称 | | type | ENUM('note','website') | 类型 | | parent_id | INT FK→folders.id | 父文件夹(树形结构) | | sort_order | INT | 排序 | | created_by | VARCHAR(100) | 创建者账号 | | created_at | DATETIME | 创建时间 | #### notes — 笔记 | 字段 | 类型 | 说明 | |------|------|------| | id | INT PK | 自增主键 | | title | VARCHAR(500) | 标题 | | content | TEXT | Tiptap 输出的 HTML | | folder_id | INT FK→folders.id | 所属文件夹 | | created_by | VARCHAR(100) | 创建者 | | updated_by | VARCHAR(100) | 最后修改者 | | share_token | VARCHAR(64) UNIQUE | 分享令牌 | | share_expires_at | DATETIME | 分享过期时间 | | created_at / updated_at | DATETIME | 时间戳 | #### tags — 标签 | 字段 | 类型 | 说明 | |------|------|------| | id | INT PK | 自增主键 | | name | VARCHAR(50) UNIQUE | 标签名 | | color | VARCHAR(20) | 颜色 | #### note_tags — 笔记-标签关联(多对多) | 字段 | 类型 | 说明 | |------|------|------| | note_id | INT FK | 笔记 ID | | tag_id | INT FK | 标签 ID | #### websites — 网站 | 字段 | 类型 | 说明 | |------|------|------| | id | INT PK | 自增主键 | | name | VARCHAR(200) | 网站名称 | | url | VARCHAR(500) | 网址 | | folder_id | INT FK | 所属文件夹 | | created_by / updated_by | VARCHAR(100) | 操作者 | | created_at / updated_at | DATETIME | 时间戳 | #### accounts — 账号 | 字段 | 类型 | 说明 | |------|------|------| | id | INT PK | 自增主键 | | website_id | INT FK | 所属网站 | | username | VARCHAR(500) | 用户名 | | password | VARCHAR(500) | 密码(明文,待加密) | | remark | TEXT | 备注 | | sort_order | INT | 排序 | | created_by / updated_by | VARCHAR(100) | 操作者 | #### uploads — 上传文件 | 字段 | 类型 | 说明 | |------|------|------| | id | INT PK | 自增主键 | | filename | VARCHAR(255) | 原始文件名 | | content_type | VARCHAR(100) | MIME 类型 | | data | LONGBLOB | 二进制数据(最大 4GB) | | size | INT | 文件大小(字节) | | created_by | VARCHAR(100) | 上传者 | | created_at | DATETIME | 上传时间 | --- ## API 接口 所有接口均以 `/api/` 为前缀。除分享页和图片读取外,所有操作需要网关注入用户身份。 ### 笔记 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/notes` | 获取笔记列表(支持 `?folder_id=` 筛选) | | POST | `/api/notes` | 创建笔记 | | GET | `/api/notes/{id}` | 获取笔记详情 | | PUT | `/api/notes/{id}` | 修改笔记 | | DELETE | `/api/notes/{id}` | 删除笔记 | | PUT | `/api/notes/{id}/move` | 移动笔记到文件夹 | | POST | `/api/notes/{id}/share` | 生成分享链接 | ### 文件夹 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/folders` | 获取文件夹列表(支持 `?type=note\|website`) | | POST | `/api/folders` | 创建文件夹 | | PUT | `/api/folders/{id}` | 重命名文件夹 | | DELETE | `/api/folders/{id}` | 删除文件夹 | ### 网站与账号 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/websites` | 获取网站列表(支持 `?folder_id=`) | | POST | `/api/websites` | 创建网站 | | PUT | `/api/websites/{id}` | 修改网站 | | DELETE | `/api/websites/{id}` | 删除网站 | | GET | `/api/websites/{id}/accounts` | 获取账号列表 | | POST | `/api/websites/{id}/accounts` | 创建账号 | | PUT | `/api/accounts/{id}` | 修改账号 | | DELETE | `/api/accounts/{id}` | 删除账号 | | PUT | `/api/accounts/sort` | 账号排序 | ### 文件 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/upload/image` | 上传图片(网关鉴权) | | GET | `/api/file/{id}` | 读取图片(公开,无需鉴权) | ### 分享 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/share/{token}` | 公开查看分享的笔记(不走网关) | | GET | `/api/shares` | 获取我的分享列表 | | DELETE | `/api/shares/{note_id}` | 取消分享 | ### 智能导入 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/import/parse` | 解析粘贴的文本,提取网站+账号信息 | --- ## 认证架构 ``` ┌─────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────┐ │ 浏览器 │ ──→ │ 统一登录页 │ ──→ │ Mokee │ ──→ │ FastAPI │ │ │ │ login.user. │ │ Gateway │ │ 后端 │ │ │ │ zgitm.com │ │ gw.server. │ │ :4006 │ │ │ │ │ │ zgitm.com │ │ │ └─────────┘ └──────────────┘ └──────┬───────┘ └──────────┘ │ 注入 X-User-* 头 X-User-Id, X-User-Account, X-User-Roles, X-System-Code ... ``` ### 请求流程 1. **用户访问** → 前端路由守卫检查 Cookie 中是否有 `token` 2. **无 Token** → 重定向到 `login.user.zgitm.com` 统一登录 3. **登录成功** → 网关设置 Cookie,用户回到应用 4. **API 请求** → Axios 拦截器从 Cookie 取 Token 放入 Authorization 头 5. **网关转发** → 验证 Token 后注入 `X-User-*` 系列请求头 6. **后端中间件** → `UserContextMiddleware` 提取请求头存入 `request.state.user` 7. **业务路由** → 通过 `UserContext.get_user_id()` 获取当前用户,按 `created_by` 过滤数据 ### 本地开发模式 设置环境变量 `DEV_MODE=true` 或添加请求头 `X-Dev-Mock-User`,后端绕过网关认证,使用默认 admin 用户。 ```bash # 启动后端 cd backend DEV_MODE=true uvicorn app:app --port 4006 # 启动前端(另一个终端) cd frontend npx vite ``` --- ## 前端架构 ### 路由 | 路径 | 组件 | 说明 | |------|------|------| | `/` | → 重定向 | 默认到 /notes | | `/notes` | NotesView | 笔记编辑器(文件夹 + 列表 + 编辑器) | | `/websites` | WebsitesView | 网站账号管理 | | `/shares` | SharesView | 分享链接管理 | ### API 调用模式 前端通过 `useApi()` 组合式函数发起请求,自动适配环境: - **生产环境**:使用 Axios 实例,拦截器自动携带 Token → 请求走网关 - **本地开发**:使用 fetch,添加 `X-Dev-Mock-User` 头模拟用户 ```js // composables/useApi.js import { useApi } from '@/composables/useApi' const { get, post, put, del } = useApi() const notes = await get('/api/notes') ``` ### 图片处理 - **上传**:粘贴/拖拽 → `POST /api/upload/image`(走网关,带 Token) - **显示**:``(走后端直连,公开读取) - **预览**:点击图片 → 全屏灯箱,带关闭按钮 ### UI 特性 - 左侧可收起导航栏(展开 "mokee编辑器",收起 "M") - 文件夹侧边栏可收起 - 笔记列表 + 编辑器双栏布局 - Ctrl+S 保存,顶部 toast 提示 - 弹窗全部为 Vue 组件(非浏览器 alert/confirm) - 移动端响应式适配(768px 断点) - 顶栏右侧「切换系统」按钮 → 跳转网关系统选择页 --- ## 生产环境 | 项目 | 值 | |------|-----| | 服务器 | 101.132.183.138 (腾讯云) | | 前端地址 | https://mokeetext.zgitm.com | | 后端地址 | https://mokeetext.server.zgitm.com | | 数据库 | MySQL 10.20.1.122:3306/mokeetext | | 日志路径 | /data/mokee/mokeetext/logs(按天轮转,保留 30 天) | | ICP 备案 | 湘ICP备19021539号 |