初始化

This commit is contained in:
zg
2026-07-15 16:08:17 +08:00
parent f0d70aded4
commit 4e0057ece5
89 changed files with 13512 additions and 0 deletions

345
docs/README.md Normal file
View File

@@ -0,0 +1,345 @@
# 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 # 双模式 APIdev 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
- **显示**`<img src="https://mokeetext.server.zgitm.com/api/file/{id}">`(走后端直连,公开读取)
- **预览**:点击图片 → 全屏灯箱,带关闭按钮
### 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号 |