f158377742d14343512a1810ee3589cc4a2158e5
终端在 Windows 上起不来 (打包规则漏解包)
- 根因: build.asarUnpack 写的是 "**/node_modules/@lydell/node-pty-*/*", 只匹配一层,
于是 prebuilds/<plat>/ 下的文件没被解包, 留在 app.asar 里
- Windows 上这些必须是磁盘上的真实文件: conpty.dll (OS loader 加载)、
OpenConsole.exe (CreateProcess)、以及 node-pty 用 worker_threads.Worker 起的
conoutSocketWorker.js —— node-pty 本身就写了
__dirname.replace('node_modules.asar', 'node_modules.asar.unpacked') 来适配
- Linux 上看不出来: 只需要一个 pty.node, Electron 的 asar 层能 dlopen 归档里的 .node
- 修复: 规则递归化为 "**/node_modules/@lydell/node-pty-*/**/*"
- 验证: 重新打包后 pty.node 已落到 app.asar.unpacked, 安装版真实 spawn 成功
Windows 保留设备名 / 尾部点空格导致落盘写错
- 新增 src/main/safe-name.ts 的 safeFileName()
- Win32 把 CON/PRN/AUX/NUL/COM1-9/LPT1-9 (带扩展名也算) 当设备, open() 打开的不是文件;
还会悄悄吃掉文件名结尾的点和空格, 导致 existsSync 判断和实际落盘对不上
- 两处落盘都接上: file-server.ts 的 targetPath()、drive.ts 的 downloadDriveFile()
(后者名字来自对端共享目录, 属不可信输入)
- 策略是"最小必要": 非法字符全平台都清, 保留名和尾点空格只在 win32 上改写,
避免动到 Linux 上合法的文件名
其他
- 终端 cwd: Windows 优先用 USERPROFILE (装了 Git Bash 时 HOME 可能是 POSIX 路径, Win32 下不存在)
- USB 面板空列表提示按平台给, 不再一律说"Linux 用户需要在 dialout 组"
分析文档与自测
- 新增 docs/windows-compat.md: 各原生模块的 N-API 情况、已有 win32 分支的位置、
已知限制 (ConPTY 需 Win10 1809+、防火墙首次弹窗、USB 需 WinUSB 驱动等)、
以及一份 Windows 真机验证清单
- 自测新增 S1-S8 组: 保留名改写、尾部点空格、非法字符、跨平台不过度清洗、
超长截断、默认 shell/cwd、asarUnpack 规则回归护栏、上传落盘 + 路径穿越
- 全部 38 条用例通过
LocalNetMsg
局域网即时通讯工具,飞书/微信聊天风格。基于 Electron + Vue 3 + TypeScript。
功能
- 局域网自动发现 (UDP 广播)
- 1 对 1 私聊,消息持久化 (SQLite)
- 富文本消息:Markdown / 代码高亮 / @提醒 / 表情
- 图片消息:粘贴板、拖拽、本地选择
- 文件传输:任意类型,大文件流式上传
- 飞书式三栏 UI,消息气泡、时间分组、发送状态
- 系统托盘最小化,后台新消息系统级通知
- 接收文件按
设置目录/YYYY-MM/自动归档
开发
环境要求: Node.js >= 20
npm install
npm run dev # 启动 Electron + 热更新
第一次启动时:
- 默认接收目录:
~/Documents/LocalNetMsg - 默认设备名: 操作系统主机名
- 两个端口自动分配 (UDP 发现 47800 / WebSocket 47900 / 文件 47901)
要测试多设备,在同一局域网的不同机器上各跑一个实例即可。
项目结构
src/
├── main/ Electron 主进程
│ ├── index.ts 入口: 窗口、托盘、IPC
│ ├── discovery.ts UDP 局域网发现
│ ├── chat-server WebSocket 服务端
│ ├── chat-client WebSocket 客户端
│ ├── file-server HTTP 文件服务
│ ├── db.ts SQLite 持久化
│ ├── settings.ts electron-store
│ ├── notify.ts 系统通知
│ └── protocol.ts 消息协议定义
├── preload/ contextBridge 桥接
└── renderer/ Vue 3 渲染层
├── src/
│ ├── views/ ChatView, SettingsView
│ ├── components/ Sidebar, MessageList, MessageItem, MessageInput
│ ├── stores/ Pinia
│ ├── api/ IPC 桥接
│ └── utils/ markdown, format
└── index.html
配置
~/AppData/Roaming/local-net-msg/config.json (electron-store):
deviceName: 本机在网络中的显示名downloadDir: 接收文件保存目录notifications: 是否启用系统通知
端口
| 用途 | 端口 | 协议 |
|---|---|---|
| 局域网发现 | 47800 | UDP |
| 聊天 | 47900 | WebSocket |
| 文件传输 | 47901 | HTTP |
被占用时自动顺延。
Description
Languages
TypeScript
70.8%
Vue
23.6%
JavaScript
5.3%
CSS
0.2%