Files
xiaoshuai a79086e4e8 feat: 网盘浏览下载 + 远程功能修复 + 连接状态同步 + Linux 图标打包
新增网盘功能
- FileServer 增加 GET /drive/meta|list|download, 每机长期 token 校验 + 目录穿越防护
- 新增 drive.ts 客户端: listDrive / getDriveRoot / downloadDriveFile / collectDriveFiles
- ipc 暴露 drive:list|root|download|openFolder|pickDir, DB 增 drive_token 列 + ALTER 迁移
- 新增 DrivePanel.vue, 聊天框加"网盘" tab, 设置页加网盘分区
- 支持整目录递归下载并保持层级

修复远程功能
- 终端: 控制端收到的 output 帧被直接丢弃 (case 'output': return), 导致 xterm 全空白
- ChatServer: ws 构造即 listen, 'listening' 可能早于 start() 挂监听, 导致永久挂起
- USB: serverAttach 自行生成 sessionId 与控制端不一致 (数据帧查表落空);
  libusb 枚举误用 getDevices() (WebUSB 语义, 只返回已授权设备) 改 loadDevices();
  control transfer 传数字 bmRequestType (node-usb v3 要字符串枚举);
  detachKernelDriver 挪到 selectConfiguration 之前 (否则 EBUSY)
- 转发 UI: store 的 onOpened 是 no-op 致对方发起的转发不显示、无轮询致流量/TTL 不刷新、
  对方发起的会话关不掉 (新增 closeSession, server 侧关闭需通知对端否则端口泄漏)、
  入口/目标补归属标注、方向标签语义统一、监听端口输入框加宽

修复"在线却显示等待重连"
- 根因: 启动时主进程先连上对端 (connectTo 早于 createMainWindow), device:wsState
  在渲染层订阅前发出去被丢弃; 之后连接一直保持, 再无 open 事件 -> UI 永久停在等待重连
- 改为推全量快照 + 渲染层 mount 时主动拉取 (app:state); 渲染层先注册监听再 await
- 通道语义改为 outgoing 或 inbound 任一 WS 活着即可用 (原来只看 outgoing)

修复 Linux 安装后没图标
- linux.icon 指向单张 PNG 时 app-builder 解析不出尺寸 (size=0), 图标被装进
  hicolor/0x0/ 非法目录, 桌面环境找不到; 改为指向 resources/icons 目录 (8 个标准尺寸)
- StartupWMClass 填的是 productName, 与窗口真实 WM_CLASS (可执行文件名) 对不上,
  任务栏找不到启动器; 改为 local-net-msg

其他
- 新增 scripts/selftest 自测框架 (两个虚拟节点 + 真实 ChatServer/ChatClient), 30 条用例全过
- 重写 scripts/make-icon.js 生成多尺寸图标集 (原脚本引用的源图已不存在, sharp 依赖也缺)
- 新增 docs/drive.md, docs/connection-status.md
2026-10-20 16:43:56 +08:00

71 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 网盘 (共享目录浏览 + 选择下载)
局域网里两台 LocalNetMsg 互传文件, 以前只能"发消息带附件" (点对点传单个文件)。
网盘功能让对方能**浏览我机器上指定的共享目录**, 挑需要的文件下载。
## 1. 组成
```
被控端 (文件持有方) 控制端 (浏览/下载方)
┌────────────────────────────┐ ┌──────────────────────────────┐
│ FileServer (0.0.0.0:47901) │ │ 聊天框 → "网盘" tab │
│ GET /drive/meta │◀── HTTP ──│ DrivePanel.vue │
│ GET /drive/list │ │ 目录浏览 / 多选 / 下载 │
│ GET /drive/download │ │ ↓ ipc │
│ ↑ 只能访问 driveDir 内的 │ │ drive.ts (客户端) │
│ 文件, 且要带对 token │ │ listDrive / downloadDrive… │
└────────────────────────────┘ └──────────────────────────────┘
```
- **文件服务器启动即开启**: `FileServer` 本来就在应用启动时跑起来了 (端口 47901),
网盘只是给它加了 3 个 `/drive/*` 路由, 不需要额外进程。
- **共享目录**: 设置 → 网盘 → 共享目录, 默认 `~/Documents/LocalNetMsg/网盘`。
对端**只能看到这个目录里的内容**, 子目录也跳不出去。
- **访问令牌**: 每台机器一个长期 token (`userData/data/drive.token`), 随局域网发现包广播,
对端拿它调 `/drive/*`。关掉"启用网盘"开关或 token 不符都会 403。
## 2. 协议
| 接口 | 说明 |
|---|---|
| `GET /drive/meta?token=` | 取网盘根目录 (仅提示用) |
| `GET /drive/list?token=&path=` | 列目录, `path` 是相对网盘根的路径 (`''` = 根) |
| `GET /drive/download?token=&path=` | 下载文件 (流式, `Content-Disposition: attachment`) |
返回的条目:
```ts
interface DriveEntry {
name: string // 文件名
path: string // 相对网盘根的路径 (下载时用它)
size: number
mtime: number
isDir: boolean
}
```
## 3. 安全
| 风险 | 处理 |
|---|---|
| 越权读任意文件 | 路径必须落在 `driveDir` 内 (resolve 后前缀校验), `..` 一律拒绝 |
| 局域网陌生人访问 | 每次请求校验 token; 开关关掉直接 404 |
| 对方版本太老 | 老版本没有 token 字段 → 控制端显示"对方版本暂不支持网盘" |
自测覆盖: `npm run selftest -- drive` (D1–D7), 包含目录穿越和错误 token 的用例。
## 4. 用法
1. 把要共享的文件丢进网盘目录 (设置里可以改位置, 面板里有"打开文件夹")
2. 在聊天框切到 **网盘** tab → 看到对方网盘的文件列表
3. 点目录进去, 勾选文件 → **下载选中**
4. 文件落到本机接收目录 (设置 → 接收目录), 面板里能看到逐个进度
**目录也支持**:
- 点目录名可以进去, "上一级"回退, 面包屑显示当前位置
- 目录行也能打勾 → **整个目录递归下载**, 本地保持原有层级
(下载 `产品文档/` → 本机得到 `产品文档/需求说明.md`、`产品文档/原型图/xx.png`)
- 递归深度上限 12 层, 防止异常目录结构把进程拖死
对方从我的网盘下载文件时, 本机会弹一条提示, 并记进审计日志 (`drive.download`)。