refactor: 白板从画笔画板改为文本记事本

原实现是 Canvas 画笔画板,与「文字白板/记事本」需求不符。重做为纯文本实时协作:
- model:strokes JSON -> content TEXT + version INT(乐观锁)+ edit_count;
  schema/dao/service 同步重构,append_stroke/replace_strokes -> update_content。
- WS 协议:stroke -> edit(发完整文本,debounce 400ms);init 下发 content/version。
  update 帧广播给他人,cleared 广播给所有人。
- 前端:canvas -> textarea;收到远端 update 用最长公共前后缀算变更区间,
  仅替换该区间并保留光标(区间前不动/后平移/内移末尾);清空/复制文本按钮。
- schema.sql 更新 whiteboard 表 DDL;DB 旧表 DROP 重建(开发环境)。
- 测试脚本与 README 同步更新。
This commit is contained in:
zikai
2026-07-21 15:00:25 +00:00
parent 7bacc33679
commit 655e039aad
13 changed files with 240 additions and 271 deletions

View File

@@ -15,9 +15,9 @@
- **文件浏览页** `GET /files`Basic Auth同 docs列出/下载/**硬删除**已上传文件;删除后不再显示。
管理 API`GET /api/admin/files``GET /api/admin/files/{id}``GET /api/admin/files/{id}/download`
`DELETE /api/admin/files/{id}`(均 Basic Auth
- **共享白板** `GET /wb/{id}`(公开,不存在则新建):Canvas 实时协作 + **清空 / 复制链接**,兼容移动端。
- **共享记事本(白板** `GET /wb/{id}`(公开,不存在则新建):纯文本实时协作 + **清空 / 复制文本**,兼容移动端。
实时同步走 `WS /ws/wb/{id}`**心跳 3s连续 5 次丢失判失活并移除**)。
- **白板管理页** `GET /wb-admin`Basic Auth同 docs查看创建时间/修改次数/上次修改时间/删除。
- **白板管理页** `GET /wb-admin`Basic Auth同 docs查看创建时间/编辑次数/上次修改时间/删除。
管理 API`GET /api/admin/wb``DELETE /api/admin/wb/{id}`(均 Basic Auth
- **反向隧道反代**`ALL /api/userPort/{userName}` -- 把请求经 SSH 反向隧道转发到该 user 的本机服务。
- **内置 SFTP/SSH 服务器**asyncssh支持 **密码 + 公钥** 鉴权,同时承载 SFTP 文件暂存与反向隧道。
@@ -168,20 +168,24 @@ SSH 服务器2022同时承载 SFTP 文件暂存与反向隧道。隧道 us
- **删除后不再显示**:列表每次进入或删除后重新 fetch前端不缓存DB 行已删,列表自然不含。
- 公开 `/api/files` 系列user.py 依赖的查重/查询/下载)保留不变。
## 共享白板
## 共享记事本(白板
白板无鉴权,任何人凭 `/wb/{id}` 即可访问并实时协作;`{id}` 须匹配
`[a-zA-Z0-9_-]{1,64}`,非法返回 400。访问不存在的 id 自动新建空板。白板长期留存
(存 MySQL `whiteboard` 表),进程重启后内容仍在。
(存 MySQL `whiteboard``content` TEXT 列),进程重启后内容仍在。
### 实时同步与心跳
- 连接:`WS /ws/wb/{id}`公开。JSON 文本帧协议:
- client -> server`{"type":"hello","client_id":"..."}`(首帧,可选)、
`{"type":"ping"}`(心跳)、`{"type":"stroke","stroke":{points,color,width}}``{"type":"clear"}`
- server -> client`{"type":"init","strokes":[...],"stroke_count":n}``{"type":"pong"}`
`{"type":"stroke","stroke":{...},"client_id":"..."}`(广播给他人,不含发送者)
`{"type":"ping"}`(心跳)、`{"type":"edit","content":"..."}`debounce 后发完整文本)、
`{"type":"clear"}`
- server -> client`{"type":"init","content":"...","version":n,"edit_count":m}`
`{"type":"pong"}``{"type":"update","content":"...","version":n,"client_id":"..."}`(广播给他人,不含发送者)、
`{"type":"cleared","client_id":"..."}`(广播给所有人)、`{"type":"error","msg":"..."}`
- **同步策略**:客户端本地编辑后 debounce 400ms 发完整文本服务端存为新版本version+1
并广播给同 board 的其他在线连接。其他端用最长公共前后缀算出变更区间,仅替换该区间并
保留本地光标位置(在变更区间前不动,在后平移,在区间内移到末尾)。
- **心跳**:客户端每 `whiteboard.heartbeat_interval_seconds`(默认 3s发一次 `ping`,服务端回 `pong`
并刷新计时。后台 reaper 每秒扫描,连续 `heartbeat_miss_threshold`(默认 5次未收到心跳
(即 15s判失活**关闭该连接并从 hub 移除**。
@@ -197,7 +201,7 @@ SSH 服务器2022同时承载 SFTP 文件暂存与反向隧道。隧道 us
- `GET /wb-admin`Basic Auth同 docs渲染 `static/whiteboard_admin.html`
- 管理 API均 Basic Auth
- `GET /api/admin/wb?limit=&offset=` -> `{total, items:[{board_id, stroke_count, created_at, updated_at}]}`
- `GET /api/admin/wb?limit=&offset=` -> `{total, items:[{board_id, edit_count, created_at, updated_at}]}`
- `DELETE /api/admin/wb/{id}` -> 删 DB 行 + 关闭该 board 所有在线 WS 连接。
## 临时文件清理