# 韫珠IM

这是一个使用 Electron 和 React 构建的仿微信 PC 客户端桌面应用。

## 📋 项目概述

**项目名称**: 韫珠IM  
**项目类型**: 基于 Electron 的桌面即时通讯客户端  
**技术栈**: Electron + React + TypeScript + Vite

### 核心功能

1. **即时通讯**: 支持文本、图片、视频、文件等多种消息类型
2. **联系人管理**: 联系人列表、详情查看、搜索功能
3. **应用中心**: 内置浏览器窗口，支持多标签页浏览
4. **消息通知**: 系统托盘、任务栏徽章、窗口标题提示
5. **媒体预览**: 独立的图片/视频预览窗口
6. **消息搜索**: 全局搜索和聊天内搜索功能
7. **日志系统**: 完整的本地日志记录功能
8. **自动更新**: 启动与定时检测、后台下载、进度显示、更新说明（releaseNotes）、下载完成后强制重启更新

---

## 📁 项目结构

```
local_client/
├── src/
│   ├── main/              # 主进程代码
│   │   └── index.ts       # 窗口管理、IPC通信、系统托盘等
│   ├── preload/           # 预加载脚本
│   │   └── index.ts       # 安全地暴露 Electron API 给渲染进程
│   └── renderer/          # 渲染进程（React应用）
│       ├── index.html     # HTML入口
│       └── src/
│           ├── App.tsx    # 主应用组件
│           ├── components/    # React组件
│           │   ├── Login.tsx          # 登录组件
│           │   ├── ContactList.tsx   # 联系人列表
│           │   ├── ChatWindow/        # 聊天窗口组件
│           │   ├── Navigation.tsx     # 导航栏
│           │   └── Modals/            # 模态框组件
│           ├── hooks/         # 自定义Hooks
│           │   ├── useAuth.ts         # 认证Hook
│           │   ├── useContacts.ts     # 联系人Hook
│           │   ├── useMessages.ts    # 消息Hook
│           │   └── useWebSocket.ts   # WebSocket Hook
│           ├── services/      # API和WebSocket服务
│           │   ├── api.ts            # REST API调用
│           │   └── websocket.ts      # WebSocket连接管理
│           ├── pages/         # 页面组件
│           │   └── ChatPage.tsx      # 聊天页面
│           ├── types/         # TypeScript类型定义
│           │   └── index.ts
│           └── utils/         # 工具函数
│               ├── logger.ts         # 日志工具
│               ├── timeUtils.ts      # 时间工具
│               ├── messageUtils.ts   # 消息工具
│               └── avatarUtils.tsx   # 头像工具
├── resources/             # 资源文件（logo等）
├── logs/                  # 日志文件
├── out/                   # 构建输出目录
├── package.json           # 项目配置
├── electron.vite.config.ts # Electron-Vite配置
└── tsconfig.json          # TypeScript配置
```

---

## 🚀 开发指南

### 环境要求

- Node.js (建议 18+)
- npm 或 yarn

### 安装依赖

```bash
npm install
```

### 开发模式

```bash
npm run dev
```

这将：
- 启动 Electron 开发服务器
- 渲染进程运行在 `http://127.0.0.1:3000`
- 支持热重载（HMR）
- API 代理：`/api` → `https://api.hnyunzhu.com`

### 开发配置说明

**electron.vite.config.ts**:
- 主进程和预加载脚本使用 `externalizeDepsPlugin`
- 渲染进程使用 React 插件
- 开发服务器端口：3000
- API 代理配置：`/api` 代理到 `https://api.hnyunzhu.com`

**主要开发文件**:
- `src/main/index.ts`: 主进程逻辑（窗口、IPC、系统托盘）
- `src/renderer/src/App.tsx`: 主应用组件
- `src/renderer/src/services/api.ts`: REST API 调用
- `src/renderer/src/services/websocket.ts`: WebSocket 连接管理

### 预览构建结果

```bash
npm run preview
```

---

## 📦 打包指南

### 构建项目

首先需要构建项目（编译 TypeScript，打包资源）：

```bash
npm run build
```

该命令会：
- 编译 TypeScript 代码
- 打包主进程代码到 `out/main/`
- 打包预加载脚本到 `out/preload/`
- 打包渲染进程到 `out/renderer/`

### 生成可执行文件

项目使用 `electron-builder` 进行打包。

#### 仅打包（不生成安装程序）

```bash
npm run pack
```

#### 构建并打包（推荐）

```bash
npm run dist
```

这将执行 `build` 和 `pack` 两个步骤，生成完整的安装包。

### 打包输出

打包完成后，安装包将输出到 `dist/` 目录：

- **Windows**: `韫珠IM Setup x.x.x.exe` (NSIS 安装程序)
- **macOS**: `韫珠IM-x.x.x.dmg` (DMG 镜像)
- **Linux**: `韫珠IM-x.x.x.AppImage` (AppImage 格式)

### 打包配置

打包配置位于 `package.json` 的 `build` 字段：

- **appId**: `com.hnyunzhu.im`
- **productName**: `韫珠IM`
- **输出目录**: `dist/`
- **应用图标**: Windows 使用 `resources/icon.ico`，macOS/Linux 使用 `resources/logo.png`
- **afterPack**: `scripts/afterPack.js`（通过 rcedit 将图标嵌入 Windows exe）
- **Windows**: 生成 NSIS 安装程序，支持自定义安装路径
- **macOS**: 生成 DMG 镜像，支持 x64 和 arm64 架构
- **Linux**: 生成 AppImage 格式

### 平台特定打包

如果需要为特定平台打包，可以使用环境变量：

```bash
# Windows
npm run dist -- --win

# macOS
npm run dist -- --mac

# Linux
npm run dist -- --linux
```

---

## 🔄 自动更新

应用使用 `electron-updater` 配合自建更新服务器实现自动更新，仅在生产环境生效（开发模式不检测更新）。

### 更新策略

- **启动时**：应用启动后自动检测一次更新；若有新版本则自动在后台下载。
- **运行中**：每隔 **5 小时** 自动检测一次更新，有更新则自动下载。
- **手动检测**：在「设置」中可点击「检查更新」随时触发一次检测。
- **下载完成后**：弹出强制更新弹窗，仅提供「立即重启并更新」，必须重启以完成安装；下载过程中在界面顶部显示下载进度条。

### 配置说明

更新地址在 `package.json` 的 `build.publish` 中配置：

```json
"publish": {
  "provider": "generic",
  "url": "https://api.hnyunzhu.com:9004/app-updates/1773848909/windows/update/"
}
```

客户端会请求该 URL 下的 `latest.yml` 判断是否有新版本。

### 发布新版本流程

1. **修改版本号**：在 `package.json` 中将 `version` 改为新版本号（如 `1.0.5`）。
2. **打包**：执行 `npm run dist`，在 `dist/` 目录得到：
   - `韫珠IM Setup x.x.x.exe`（安装包）
   - `latest.yml`（更新元数据，electron-updater 据此检测与下载）
3. **（可选）填写更新说明**：编辑 `dist/latest.yml`，在末尾增加 `releaseNotes` 字段，应用会在「有更新」和「下载完成」时展示该内容：

   ```yaml
   releaseNotes: |
     1. 修复若干问题
     2. 新增 xxx 功能
     3. 优化性能
   ```

   单行可写为：`releaseNotes: "1. 修复若干问题；2. 新增 xxx 功能"`
4. **上传**：将 `dist/latest.yml` 和 `dist/韫珠IM Setup x.x.x.exe`（及同名的 `.exe.blockmap`，若有）上传到上述 `publish.url` 对应目录，保证可通过 `https://api.hnyunzhu.com:9004/app-updates/1773848909/windows/update/latest.yml` 和同目录下的 exe 被访问。

### 服务端要求

- 需支持 HTTPS（当前为端口 9004）。
- 安装包响应建议带 **Content-Length** 头，否则下载进度可能无法正确显示百分比。
- 无需 CORS（更新请求在主进程内发起）。

### 用户端表现

- **发现新版本**：顶部出现绿色条「正在下载更新…」及进度条与百分比；可继续使用应用（后台下载）。
- **设置中**：「检查更新」按钮可手动检测；若处于下载中，会显示进度条与更新说明（若 `latest.yml` 中有 `releaseNotes`）。
- **下载完成**：弹出「新版本已下载，请重启以完成更新」弹窗，可展示本次版本的更新说明，仅可点击「立即重启并更新」完成安装。

### 相关依赖与代码

- **依赖**：`electron-updater`（见 `package.json` 的 `dependencies`）。
- **主进程**：`src/main/index.ts` 中注册 `autoUpdater` 事件、`check-for-updates` IPC、5 小时定时检测及 `quit-and-install`。
- **渲染进程**：`src/renderer/src/App.tsx` 中监听更新事件、展示下载进度与强制更新弹窗；`src/renderer/src/components/Modals/SettingsModal.tsx` 中「检查更新」按钮与状态展示。

---

## 🏗️ 技术架构

### 进程架构

1. **主进程** (`src/main/index.ts`)
   - 窗口管理（主窗口、浏览器窗口、预览窗口）
   - 系统托盘和通知
   - IPC 通信处理
   - 文件系统操作
   - 日志管理

2. **渲染进程** (`src/renderer/`)
   - React 应用
   - UI 渲染和用户交互
   - 业务逻辑处理

3. **预加载脚本** (`src/preload/index.ts`)
   - 安全桥接主进程和渲染进程
   - 暴露 Electron API 给渲染进程

### 通信方式

- **IPC (Inter-Process Communication)**: 主进程与渲染进程通信
- **WebSocket**: 实时消息推送
- **REST API**: HTTP 请求（通过 Vite 代理）

### 关键依赖

- `electron`: ^28.0.0 - Electron 框架
- `electron-vite`: ^2.0.0 - Electron + Vite 构建工具
- `react`: ^18.2.0 - React UI 框架
- `typescript`: ^5.0.2 - TypeScript 语言
- `vite`: ^5.0.0 - 构建工具
- `crypto-js`: ^4.2.0 - 加密库（用于签名认证）
- `electron-builder`: ^26.8.1 - 打包工具

---

## 🔑 关键代码说明

### 应用中心实现原理

在 `src/main/index.ts` 中：

```typescript
mainWindow.webContents.setWindowOpenHandler((details) => {
  // 拦截所有 http/https 链接
  if (details.url.startsWith('http')) {
    createInternalBrowserWindow(details.url)
    return { action: 'deny' } // 阻止默认行为
  }
  return { action: 'allow' }
})
```

在 `src/renderer/src/App.tsx` 中：
链接必须带有 `target="_blank"` 属性才能触发上述拦截。

```tsx
<a href="..." target="_blank">...</a>
```

### 窗口管理

项目支持多种窗口类型：
- **主窗口**: 聊天主界面
- **浏览器窗口**: 应用中心，支持多标签页（使用 BrowserView）
- **预览窗口**: 图片/视频预览窗口

### WebSocket 连接

WebSocket 服务位于 `src/renderer/src/services/websocket.ts`，支持：
- 自动重连机制
- 心跳保活（ping/pong）
- 消息推送处理

---

## ⚠️ 注意事项

1. **API 配置**: 
   - 开发环境通过 Vite 代理访问 API
   - 生产环境需要直接连接 `https://api.hnyunzhu.com`

2. **日志文件**: 
   - 存储在 `logs/` 目录
   - 按日期命名（如 `2026-02-26.log`）

3. **资源文件**: 
   - `app_icon.png` 用于应用图标（已配置）
   - `resources/logo.png` 用于其他资源
   - **图标要求**: 图标文件必须至少为 256x256 像素，当前使用的 `app_icon.png` 已满足要求

4. **窗口管理**: 
   - 支持主窗口、浏览器窗口、预览窗口等多种窗口类型
   - 使用 BrowserView 实现多标签页功能

5. **安全设置**: 
   - 使用 `contextIsolation` 和 `sandbox` 模式确保安全性
   - 通过预加载脚本安全地暴露 API

6. **打包注意事项**:
   - 首次打包会下载对应平台的 Electron 二进制文件，可能需要一些时间
   - 确保有足够的磁盘空间（至少 500MB）
   - Windows 打包需要安装 NSIS（electron-builder 会自动处理）
   - **图标问题**: 如果遇到 `image must be at least 256x256` 错误，说明图标尺寸不够，需要准备至少 256x256 像素的图标文件，或暂时移除图标配置
   - **代码签名问题**: Windows 打包时如果遇到符号链接权限错误，这是因为 electron-builder 尝试下载代码签名工具（`winCodeSign`），其压缩包中包含 macOS 符号链接文件，在非管理员模式下解压会失败。当前配置已通过 `forceCodeSigning: false`、`signAndEditExecutable: false` 和环境变量禁用代码签名。
   - **备选方案**: 如果 NSIS 安装程序打包失败，可以：
     1. 使用 `npm run dist:portable` 生成便携版（不需要签名）
     2. 直接使用 `dist/win-unpacked/韫珠IM.exe` 运行应用
     3. 以管理员权限运行 PowerShell 后再打包（解决符号链接权限问题）

7. **Windows exe 图标嵌入机制**:
   - `signAndEditExecutable: false` 会导致 electron-builder 跳过图标嵌入步骤，exe 文件和任务栏将无法显示自定义图标
   - 项目通过 `afterPack` 钩子 (`scripts/afterPack.js`) 使用 `rcedit` 手动将 `resources/icon.ico` 嵌入到 exe 中，绕过了 `winCodeSign` 的下载问题
   - **不要删除** `scripts/afterPack.js` 文件和 `rcedit` 依赖，否则打包后 exe 和任务栏将没有图标
   - 更换图标时，替换 `resources/icon.ico` 即可。ico 文件建议包含多尺寸（16x16、32x32、48x48、256x256），Windows 在不同场景使用不同尺寸：
     - 16x16：任务栏、窗口标题栏
     - 32x32：桌面快捷方式（小图标）
     - 48x48：资源管理器
     - 256x256：资源管理器大图标视图
   - 托盘图标由 `src/main/index.ts` 中的 `Tray` 在运行时从文件加载，不依赖 exe 嵌入
   - 安装程序图标由 NSIS 单独处理，不受 `signAndEditExecutable` 影响

---

## 📝 开发脚本说明

- `npm run dev`: 启动开发服务器
- `npm run build`: 构建项目（编译 TypeScript，打包资源）
- `npm run preview`: 预览构建结果
- `npm run pack`: 仅打包（不重新构建）
- `npm run dist`: 构建并打包 NSIS 安装程序（推荐用于生产环境）
- `npm run dist:portable`: 构建并打包便携版（单 exe，无需安装）

---

## 📄 许可证

MIT
