diff --git a/.github/workflows/build-electron.yml b/.github/workflows/build-electron.yml
new file mode 100644
index 0000000..98c2213
--- /dev/null
+++ b/.github/workflows/build-electron.yml
@@ -0,0 +1,77 @@
+name: Build Electron App
+
+on:
+ push:
+ branches:
+ - main
+ tags:
+ - 'v*'
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: windows-latest
+
+ strategy:
+ matrix:
+ node-version: [20.x]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v2
+ with:
+ version: 10
+
+ - name: Get pnpm store directory
+ id: pnpm-cache
+ shell: bash
+ run: |
+ echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
+
+ - name: Setup pnpm cache
+ uses: actions/cache@v3
+ with:
+ path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-pnpm-store-
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build Vite project
+ run: pnpm run build
+
+ - name: Compile Electron files
+ run: |
+ npx tsc electron/main.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+ npx tsc electron/preload.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+
+ - name: Build Electron app
+ run: pnpm run electron-build
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: electron-builds
+ path: dist/electron/
+ retention-days: 30
+
+ - name: Create Release and Upload Assets
+ if: startsWith(github.ref, 'refs/tags/v')
+ uses: softprops/action-gh-release@v1
+ with:
+ files: |
+ dist/electron/*.exe
+ dist/electron/*.exe.blockmap
+ draft: false
+ prerelease: false
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/ELECTRON_BUILD.md b/ELECTRON_BUILD.md
new file mode 100644
index 0000000..70aa53c
--- /dev/null
+++ b/ELECTRON_BUILD.md
@@ -0,0 +1,272 @@
+# Electron 应用构建指南
+
+本文档说明如何构建和发布高级时钟 Electron 应用为 Windows EXE 文件。
+
+## 快速开始(Windows)
+
+### 使用自动化脚本
+
+我们提供了两个自动化脚本来简化构建过程:
+
+#### 方式 1:使用批处理脚本(推荐)
+
+1. 在项目根目录找到 `build-electron.bat`
+2. 双击运行脚本
+3. 脚本会自动完成所有构建步骤
+4. EXE 文件会生成在 `dist/electron/` 目录中
+
+#### 方式 2:使用 PowerShell 脚本
+
+1. 打开 PowerShell
+2. 进入项目目录
+3. 运行命令:
+ ```powershell
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+ .\build-electron.ps1
+ ```
+4. EXE 文件会生成在 `dist/electron/` 目录中
+
+### 手动构建步骤
+
+如果自动化脚本无法使用,可以手动执行以下步骤:
+
+```bash
+# 1. 安装依赖
+pnpm install
+
+# 2. 构建 Vite 项目
+pnpm run build
+
+# 3. 编译 Electron 主进程
+npx tsc electron/main.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+
+# 4. 编译 Electron 预加载脚本
+npx tsc electron/preload.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+
+# 5. 构建 Electron 应用
+pnpm run electron-build
+```
+
+## 前置要求
+
+- **Windows 系统**(Windows 10 或更高版本)
+- **Node.js 20+**:从 https://nodejs.org/ 下载安装
+- **pnpm 10+**:通过 `npm install -g pnpm` 安装
+
+## 输出文件
+
+构建完成后,以下文件会生成在 `dist/electron/` 目录中:
+
+| 文件名 | 说明 |
+|--------|------|
+| `Advanced Clock.exe` | NSIS 安装程序(推荐用于发布) |
+| `Advanced Clock Setup.exe` | 便携式可执行文件(无需安装) |
+| `Advanced Clock Setup.exe.blockmap` | 增量更新文件 |
+
+## 发布到 GitHub Releases
+
+### 手动上传
+
+1. 在 GitHub 仓库页面点击 **Releases**
+2. 点击 **Create a new release**
+3. 填写版本标签(如 `v1.0.0`)和发布说明
+4. 在 **Attach binaries** 部分上传 `Advanced Clock.exe` 文件
+5. 点击 **Publish release**
+
+### 使用 GitHub CLI
+
+```bash
+# 创建发布并上传文件
+gh release create v1.0.0 dist/electron/Advanced\ Clock.exe --title "Advanced Clock v1.0.0" --notes "Release notes here"
+```
+
+## 开发模式
+
+在开发过程中测试 Electron 应用:
+
+### 方式 1:使用两个终端
+
+```bash
+# 终端 1:启动 Vite 开发服务器
+pnpm run dev
+
+# 终端 2:启动 Electron 应用
+pnpm run electron-dev
+```
+
+### 方式 2:直接运行
+
+```bash
+# 构建后直接运行 Electron 应用
+pnpm run build
+npx electron .
+```
+
+## 项目结构
+
+```
+advanced-clock-site/
+├── client/ # React 应用源代码
+│ ├── src/
+│ │ ├── pages/ # 页面组件
+│ │ ├── components/ # UI 组件
+│ │ ├── contexts/ # React Context
+│ │ ├── utils/ # 工具函数
+│ │ └── App.tsx # 主应用组件
+│ └── index.html # HTML 入口
+├── electron/ # Electron 相关文件
+│ ├── main.ts # Electron 主进程
+│ ├── main.js # 编译后的主进程
+│ ├── preload.ts # 预加载脚本
+│ └── preload.js # 编译后的预加载脚本
+├── dist/ # 构建输出
+│ ├── index.html # 打包的 Web 应用
+│ ├── assets/ # 静态资源
+│ └── electron/ # Electron 构建输出(EXE 文件)
+├── build-electron.bat # Windows 批处理构建脚本
+├── build-electron.ps1 # PowerShell 构建脚本
+├── electron-builder.yml # Electron Builder 配置
+├── package.json # 项目配置和脚本
+├── vite.config.ts # Vite 配置
+└── tsconfig.json # TypeScript 配置
+```
+
+## 配置说明
+
+### electron-builder.yml
+
+定义了 Windows 安装程序的配置:
+
+```yaml
+appId: com.advancedclock.app # 应用唯一标识符
+productName: Advanced Clock # 应用显示名称
+files: # 包含在打包中的文件
+ - dist/**/* # 构建的 Web 应用
+ - electron/**/* # Electron 文件
+ - package.json
+win:
+ target: # 构建目标
+ - nsis # NSIS 安装程序
+ - portable # 便携式可执行文件
+nsis:
+ oneClick: false # 允许自定义安装目录
+ allowToChangeInstallationDirectory: true
+ createDesktopShortcut: true # 创建桌面快捷方式
+ createStartMenuShortcut: true # 创建开始菜单快捷方式
+```
+
+### package.json 中的脚本
+
+```json
+{
+ "scripts": {
+ "electron-dev": "vite build && electron .",
+ "electron-build": "vite build && electron-builder"
+ },
+ "build": {
+ "appId": "com.advancedclock.app",
+ "productName": "Advanced Clock",
+ "files": ["dist/**/*", "electron/**/*", "package.json"],
+ "win": {
+ "target": ["nsis", "portable"],
+ "arch": ["x64"]
+ },
+ "nsis": {
+ "oneClick": false,
+ "allowToChangeInstallationDirectory": true,
+ "createDesktopShortcut": true,
+ "createStartMenuShortcut": true
+ }
+ }
+}
+```
+
+## 常见问题
+
+### Q: 构建时出现 "electron not found" 错误
+
+A: 确保已安装依赖:
+```bash
+pnpm install
+```
+
+### Q: 如何自定义应用图标?
+
+A: 在项目根目录创建 `assets/` 文件夹,放入以下文件:
+- `icon.png` - 应用图标(512x512 或更大)
+- `icon.ico` - Windows 图标
+
+然后重新构建应用。Electron Builder 会自动使用这些图标。
+
+### Q: 如何签名 EXE 文件?
+
+A: 在 `electron-builder.yml` 中配置:
+```yaml
+win:
+ certificateFile: path/to/certificate.pfx
+ certificatePassword: your-password
+ signingHashAlgorithms:
+ - sha256
+```
+
+### Q: 安装程序太大怎么办?
+
+A: 可以在 `electron-builder.yml` 中启用压缩:
+```yaml
+win:
+ certificateFile: null
+ signingHashAlgorithms:
+ - sha256
+```
+
+### Q: 如何创建便携式版本(无需安装)?
+
+A: 便携式版本已经包含在构建输出中。使用 `Advanced Clock Setup.exe` 文件。
+
+### Q: 如何自动检查更新?
+
+A: 可以集成 `electron-updater`:
+```bash
+pnpm add electron-updater
+```
+
+然后在 `electron/main.ts` 中配置更新逻辑。
+
+## 故障排除
+
+### 构建失败
+
+1. 清除缓存:
+ ```bash
+ rm -r node_modules dist
+ pnpm install
+ ```
+
+2. 检查 Node.js 版本:
+ ```bash
+ node --version # 应该是 v20 或更高
+ ```
+
+3. 检查磁盘空间:确保有至少 1GB 的可用空间
+
+### 应用无法启动
+
+1. 检查 `dist/index.html` 是否存在
+2. 查看 Electron 开发者工具(按 F12)中的错误信息
+3. 检查 `electron/main.js` 是否正确编译
+
+### 安装程序无法运行
+
+1. 确保 Windows 系统已更新
+2. 尝试以管理员身份运行安装程序
+3. 检查是否被防病毒软件阻止
+
+## 更多信息
+
+- [Electron 官方文档](https://www.electronjs.org/docs)
+- [Electron Builder 文档](https://www.electron.build/)
+- [NSIS 文档](https://nsis.sourceforge.io/Docs/)
+
+## 支持
+
+如有问题,请在 GitHub Issues 中提报。
diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md
new file mode 100644
index 0000000..4ddfd37
--- /dev/null
+++ b/RELEASE_GUIDE.md
@@ -0,0 +1,213 @@
+# GitHub Release 发布指南
+
+本指南说明如何将构建好的 EXE 文件发布到 GitHub Releases。
+
+## 前置准备
+
+1. **构建 EXE 文件**:按照 `ELECTRON_BUILD.md` 中的说明构建应用
+2. **GitHub 仓库访问权限**:确保您有仓库的推送权限
+3. **GitHub CLI**(可选):用于命令行发布
+
+## 方式 1:通过 GitHub 网页界面(推荐)
+
+### 步骤 1:创建 Release
+
+1. 访问 GitHub 仓库:https://github.com/Yejack819/Advanced-clock-web
+2. 点击右侧的 **Releases** 链接
+3. 点击 **Create a new release** 按钮
+
+### 步骤 2:填写发布信息
+
+| 字段 | 说明 | 示例 |
+|------|------|------|
+| **Tag version** | 版本标签 | `v1.0.0` |
+| **Release title** | 发布标题 | `Advanced Clock v1.0.0` |
+| **Describe this release** | 发布说明 | 功能说明、改进、已知问题等 |
+
+### 步骤 3:上传 EXE 文件
+
+1. 在 **Attach binaries** 部分,点击 **Choose files**
+2. 选择构建输出目录 `dist/electron/` 中的文件:
+ - `Advanced Clock.exe` - NSIS 安装程序(推荐)
+ - `Advanced Clock Setup.exe` - 便携式版本(可选)
+
+### 步骤 4:发布
+
+1. 确认信息无误
+2. 点击 **Publish release** 按钮
+3. Release 创建完成,用户可以下载 EXE 文件
+
+## 方式 2:使用 GitHub CLI
+
+### 安装 GitHub CLI
+
+```bash
+# Windows (Chocolatey)
+choco install gh
+
+# Windows (Scoop)
+scoop install gh
+
+# macOS
+brew install gh
+
+# Linux
+# 详见 https://github.com/cli/cli#installation
+```
+
+### 登录 GitHub
+
+```bash
+gh auth login
+```
+
+### 创建 Release 并上传文件
+
+```bash
+# 创建 Release 并上传单个文件
+gh release create v1.0.0 dist/electron/Advanced\ Clock.exe \
+ --title "Advanced Clock v1.0.0" \
+ --notes "Release notes here"
+
+# 创建 Release 并上传多个文件
+gh release create v1.0.0 \
+ dist/electron/Advanced\ Clock.exe \
+ dist/electron/Advanced\ Clock\ Setup.exe \
+ --title "Advanced Clock v1.0.0" \
+ --notes "Release notes here"
+
+# 创建草稿 Release(不立即发布)
+gh release create v1.0.0 dist/electron/Advanced\ Clock.exe \
+ --title "Advanced Clock v1.0.0" \
+ --draft
+```
+
+### 查看已发布的 Release
+
+```bash
+# 列出所有 Release
+gh release list
+
+# 查看特定 Release 的详情
+gh release view v1.0.0
+```
+
+## 方式 3:使用 Git 标签自动发布
+
+如果配置了 GitHub Actions 工作流(需要 workflow 权限),可以通过 Git 标签自动发布:
+
+```bash
+# 创建标签
+git tag v1.0.0
+
+# 推送标签到 GitHub
+git push origin v1.0.0
+
+# GitHub Actions 会自动构建并创建 Release
+```
+
+## 发布说明模板
+
+以下是一个发布说明的模板:
+
+```markdown
+# Advanced Clock v1.0.0
+
+## 新功能
+- ✨ 添加 Electron 桌面应用支持
+- 🎨 改进 UI 设计
+- 🚀 性能优化
+
+## 改进
+- 📱 响应式设计改进
+- 🔧 代码重构和优化
+- 📚 文档更新
+
+## 修复
+- 🐛 修复倒计时暂停/恢复问题
+- 🐛 修复日期显示格式问题
+
+## 已知问题
+- 某些旧版 Windows 系统可能需要更新 .NET Framework
+
+## 下载
+
+- **Advanced Clock.exe** - NSIS 安装程序(推荐)
+- **Advanced Clock Setup.exe** - 便携式版本
+
+## 安装说明
+
+### 使用 NSIS 安装程序
+1. 下载 `Advanced Clock.exe`
+2. 双击运行安装程序
+3. 按照提示完成安装
+
+### 使用便携式版本
+1. 下载 `Advanced Clock Setup.exe`
+2. 直接运行,无需安装
+
+## 系统要求
+- Windows 10 或更高版本
+- 至少 100MB 可用磁盘空间
+
+## 反馈
+
+如有问题或建议,请在 [GitHub Issues](https://github.com/Yejack819/Advanced-clock-web/issues) 中提报。
+```
+
+## 版本号规范
+
+建议使用语义化版本号(Semantic Versioning):
+
+```
+v主版本号.次版本号.修订号
+
+示例:
+v1.0.0 - 初始版本
+v1.1.0 - 添加新功能
+v1.1.1 - 修复 bug
+v2.0.0 - 重大更新
+```
+
+## 发布清单
+
+在发布前,请检查以下项目:
+
+- [ ] 代码已提交到 GitHub
+- [ ] 版本号已更新(package.json)
+- [ ] CHANGELOG 已更新
+- [ ] EXE 文件已成功构建
+- [ ] EXE 文件已测试可正常运行
+- [ ] Release 信息已准备好
+- [ ] 发布说明已编写
+
+## 常见问题
+
+### Q: 如何更新已发布的 Release?
+
+A: GitHub 不允许编辑已发布 Release 的文件。如需更新,请:
+1. 删除旧 Release
+2. 创建新 Release 并上传更新的文件
+
+或者创建新版本号的 Release。
+
+### Q: 如何删除 Release?
+
+A: 在 Release 页面点击 **Delete** 按钮。注意:删除 Release 不会删除 Git 标签。
+
+### Q: 用户下载后如何安装?
+
+A: 用户可以:
+1. 下载 EXE 文件
+2. 双击运行
+3. 按照安装程序提示完成安装
+
+### Q: 如何提供更新检查功能?
+
+A: 可以集成 `electron-updater`,自动检查和下载更新。详见 `ELECTRON_BUILD.md`。
+
+## 更多信息
+
+- [GitHub Releases 文档](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases)
+- [GitHub CLI 文档](https://cli.github.com/manual/)
+- [语义化版本](https://semver.org/lang/zh-CN/)
diff --git a/build-electron.bat b/build-electron.bat
new file mode 100644
index 0000000..f0b2426
--- /dev/null
+++ b/build-electron.bat
@@ -0,0 +1,84 @@
+@echo off
+REM Advanced Clock - Electron Build Script for Windows
+REM This script builds the Electron application and creates Windows installers
+
+echo.
+echo ========================================
+echo Advanced Clock - Electron Build Script
+echo ========================================
+echo.
+
+REM Check if Node.js is installed
+where node >nul 2>nul
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: Node.js is not installed or not in PATH
+ echo Please install Node.js from https://nodejs.org/
+ pause
+ exit /b 1
+)
+
+REM Check if pnpm is installed
+where pnpm >nul 2>nul
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: pnpm is not installed
+ echo Installing pnpm...
+ npm install -g pnpm
+)
+
+echo.
+echo Step 1: Installing dependencies...
+call pnpm install
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: Failed to install dependencies
+ pause
+ exit /b 1
+)
+
+echo.
+echo Step 2: Building Vite project...
+call pnpm run build
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: Failed to build Vite project
+ pause
+ exit /b 1
+)
+
+echo.
+echo Step 3: Compiling Electron main process...
+call npx tsc electron/main.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: Failed to compile main.ts
+ pause
+ exit /b 1
+)
+
+echo.
+echo Step 4: Compiling Electron preload script...
+call npx tsc electron/preload.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: Failed to compile preload.ts
+ pause
+ exit /b 1
+)
+
+echo.
+echo Step 5: Building Electron application...
+call pnpm run electron-build
+if %ERRORLEVEL% NEQ 0 (
+ echo Error: Failed to build Electron application
+ pause
+ exit /b 1
+)
+
+echo.
+echo ========================================
+echo Build completed successfully!
+echo ========================================
+echo.
+echo Output files are located in: dist\electron\
+echo.
+echo Files created:
+echo - Advanced Clock.exe (NSIS Installer)
+echo - Advanced Clock Setup.exe (Portable Executable)
+echo.
+pause
diff --git a/build-electron.ps1 b/build-electron.ps1
new file mode 100644
index 0000000..34be358
--- /dev/null
+++ b/build-electron.ps1
@@ -0,0 +1,86 @@
+# Advanced Clock - Electron Build Script for Windows (PowerShell)
+# This script builds the Electron application and creates Windows installers
+
+Write-Host ""
+Write-Host "========================================"
+Write-Host "Advanced Clock - Electron Build Script"
+Write-Host "========================================"
+Write-Host ""
+
+# Check if Node.js is installed
+try {
+ $nodeVersion = node --version
+ Write-Host "✓ Node.js found: $nodeVersion"
+} catch {
+ Write-Host "✗ Error: Node.js is not installed or not in PATH"
+ Write-Host "Please install Node.js from https://nodejs.org/"
+ Read-Host "Press Enter to exit"
+ exit 1
+}
+
+# Check if pnpm is installed
+try {
+ $pnpmVersion = pnpm --version
+ Write-Host "✓ pnpm found: $pnpmVersion"
+} catch {
+ Write-Host "! pnpm not found, installing..."
+ npm install -g pnpm
+}
+
+Write-Host ""
+Write-Host "Step 1: Installing dependencies..."
+pnpm install
+if ($LASTEXITCODE -ne 0) {
+ Write-Host "✗ Error: Failed to install dependencies"
+ Read-Host "Press Enter to exit"
+ exit 1
+}
+
+Write-Host ""
+Write-Host "Step 2: Building Vite project..."
+pnpm run build
+if ($LASTEXITCODE -ne 0) {
+ Write-Host "✗ Error: Failed to build Vite project"
+ Read-Host "Press Enter to exit"
+ exit 1
+}
+
+Write-Host ""
+Write-Host "Step 3: Compiling Electron main process..."
+npx tsc electron/main.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+if ($LASTEXITCODE -ne 0) {
+ Write-Host "✗ Error: Failed to compile main.ts"
+ Read-Host "Press Enter to exit"
+ exit 1
+}
+
+Write-Host ""
+Write-Host "Step 4: Compiling Electron preload script..."
+npx tsc electron/preload.ts --outDir electron --module esnext --target es2020 --lib es2020 --moduleResolution node --esModuleInterop --skipLibCheck --strict false
+if ($LASTEXITCODE -ne 0) {
+ Write-Host "✗ Error: Failed to compile preload.ts"
+ Read-Host "Press Enter to exit"
+ exit 1
+}
+
+Write-Host ""
+Write-Host "Step 5: Building Electron application..."
+pnpm run electron-build
+if ($LASTEXITCODE -ne 0) {
+ Write-Host "✗ Error: Failed to build Electron application"
+ Read-Host "Press Enter to exit"
+ exit 1
+}
+
+Write-Host ""
+Write-Host "========================================"
+Write-Host "✓ Build completed successfully!"
+Write-Host "========================================"
+Write-Host ""
+Write-Host "Output files are located in: dist\electron\"
+Write-Host ""
+Write-Host "Files created:"
+Write-Host "- Advanced Clock.exe (NSIS Installer)"
+Write-Host "- Advanced Clock Setup.exe (Portable Executable)"
+Write-Host ""
+Read-Host "Press Enter to exit"
diff --git a/electron-builder.yml b/electron-builder.yml
new file mode 100644
index 0000000..9cf371d
--- /dev/null
+++ b/electron-builder.yml
@@ -0,0 +1,24 @@
+appId: com.advancedclock.app
+productName: Advanced Clock
+directories:
+ buildResources: assets
+ output: dist/electron
+files:
+ - dist/**/*
+ - electron/**/*
+ - package.json
+ - node_modules/**/*
+win:
+ target:
+ - nsis
+ - portable
+ certificateFile: null
+ certificatePassword: null
+ signingHashAlgorithms:
+ - sha256
+nsis:
+ oneClick: false
+ allowToChangeInstallationDirectory: true
+ createDesktopShortcut: true
+ createStartMenuShortcut: true
+ shortcutName: Advanced Clock
diff --git a/electron/main.js b/electron/main.js
new file mode 100644
index 0000000..0951c03
--- /dev/null
+++ b/electron/main.js
@@ -0,0 +1,83 @@
+import { app, BrowserWindow, Menu } from 'electron';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import isDev from 'electron-is-dev';
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+let mainWindow = null;
+function createWindow() {
+ mainWindow = new BrowserWindow({
+ width: 1400,
+ height: 900,
+ minWidth: 800,
+ minHeight: 600,
+ webPreferences: {
+ preload: path.join(__dirname, 'preload.js'),
+ nodeIntegration: false,
+ contextIsolation: true,
+ },
+ icon: path.join(__dirname, '../assets/icon.png'),
+ });
+ const startUrl = isDev
+ ? 'http://localhost:5173'
+ : `file://${path.join(__dirname, '../dist/index.html')}`;
+ mainWindow.loadURL(startUrl);
+ if (isDev) {
+ mainWindow.webContents.openDevTools();
+ }
+ mainWindow.on('closed', () => {
+ mainWindow = null;
+ });
+}
+app.on('ready', createWindow);
+app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') {
+ app.quit();
+ }
+});
+app.on('activate', () => {
+ if (mainWindow === null) {
+ createWindow();
+ }
+});
+// 创建应用菜单
+const menu = Menu.buildFromTemplate([
+ {
+ label: 'File',
+ submenu: [
+ {
+ label: 'Exit',
+ accelerator: 'CmdOrCtrl+Q',
+ click: () => {
+ app.quit();
+ },
+ },
+ ],
+ },
+ {
+ label: 'Edit',
+ submenu: [
+ { role: 'undo' },
+ { role: 'redo' },
+ { type: 'separator' },
+ { role: 'cut' },
+ { role: 'copy' },
+ { role: 'paste' },
+ ],
+ },
+ {
+ label: 'View',
+ submenu: [
+ { role: 'reload' },
+ { role: 'forceReload' },
+ { role: 'toggleDevTools' },
+ { type: 'separator' },
+ { role: 'resetZoom' },
+ { role: 'zoomIn' },
+ { role: 'zoomOut' },
+ { type: 'separator' },
+ { role: 'togglefullscreen' },
+ ],
+ },
+]);
+Menu.setApplicationMenu(menu);
diff --git a/electron/main.ts b/electron/main.ts
new file mode 100644
index 0000000..75aa43b
--- /dev/null
+++ b/electron/main.ts
@@ -0,0 +1,95 @@
+import { app, BrowserWindow, Menu, ipcMain } from 'electron';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import isDev from 'electron-is-dev';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+let mainWindow: BrowserWindow | null = null;
+
+function createWindow() {
+ mainWindow = new BrowserWindow({
+ width: 1400,
+ height: 900,
+ minWidth: 800,
+ minHeight: 600,
+ webPreferences: {
+ preload: path.join(__dirname, 'preload.js'),
+ nodeIntegration: false,
+ contextIsolation: true,
+ },
+ icon: path.join(__dirname, '../assets/icon.png'),
+ });
+
+ const startUrl = isDev
+ ? 'http://localhost:5173'
+ : `file://${path.join(__dirname, '../dist/index.html')}`;
+
+ mainWindow.loadURL(startUrl);
+
+ if (isDev) {
+ mainWindow.webContents.openDevTools();
+ }
+
+ mainWindow.on('closed', () => {
+ mainWindow = null;
+ });
+}
+
+app.on('ready', createWindow);
+
+app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') {
+ app.quit();
+ }
+});
+
+app.on('activate', () => {
+ if (mainWindow === null) {
+ createWindow();
+ }
+});
+
+// 创建应用菜单
+const menu = Menu.buildFromTemplate([
+ {
+ label: 'File',
+ submenu: [
+ {
+ label: 'Exit',
+ accelerator: 'CmdOrCtrl+Q',
+ click: () => {
+ app.quit();
+ },
+ },
+ ],
+ },
+ {
+ label: 'Edit',
+ submenu: [
+ { role: 'undo' },
+ { role: 'redo' },
+ { type: 'separator' },
+ { role: 'cut' },
+ { role: 'copy' },
+ { role: 'paste' },
+ ],
+ },
+ {
+ label: 'View',
+ submenu: [
+ { role: 'reload' },
+ { role: 'forceReload' },
+ { role: 'toggleDevTools' },
+ { type: 'separator' },
+ { role: 'resetZoom' },
+ { role: 'zoomIn' },
+ { role: 'zoomOut' },
+ { type: 'separator' },
+ { role: 'togglefullscreen' },
+ ],
+ },
+]);
+
+Menu.setApplicationMenu(menu);
diff --git a/electron/preload.js b/electron/preload.js
new file mode 100644
index 0000000..704805b
--- /dev/null
+++ b/electron/preload.js
@@ -0,0 +1,17 @@
+import { contextBridge, ipcRenderer } from 'electron';
+contextBridge.exposeInMainWorld('electron', {
+ ipcRenderer: {
+ send: (channel, args) => {
+ ipcRenderer.send(channel, args);
+ },
+ on: (channel, func) => {
+ ipcRenderer.on(channel, (event, ...args) => func(...args));
+ },
+ once: (channel, func) => {
+ ipcRenderer.once(channel, (event, ...args) => func(...args));
+ },
+ invoke: (channel, args) => {
+ return ipcRenderer.invoke(channel, args);
+ },
+ },
+});
diff --git a/electron/preload.ts b/electron/preload.ts
new file mode 100644
index 0000000..83e2ebc
--- /dev/null
+++ b/electron/preload.ts
@@ -0,0 +1,18 @@
+import { contextBridge, ipcRenderer } from 'electron';
+
+contextBridge.exposeInMainWorld('electron', {
+ ipcRenderer: {
+ send: (channel: string, args: any) => {
+ ipcRenderer.send(channel, args);
+ },
+ on: (channel: string, func: (...args: any[]) => void) => {
+ ipcRenderer.on(channel, (event, ...args) => func(...args));
+ },
+ once: (channel: string, func: (...args: any[]) => void) => {
+ ipcRenderer.once(channel, (event, ...args) => func(...args));
+ },
+ invoke: (channel: string, args: any) => {
+ return ipcRenderer.invoke(channel, args);
+ },
+ },
+});