基于客户需求,需要开发一款Windows桌面应用程序,具备以下核心功能:
| 技术组件 | 选型 | 理由 |
|---|---|---|
| 桌面框架 | Electron 28+ | 跨平台、内置Chromium、生态成熟、易于开发 |
| 前端框架 | React 18 + TypeScript | 组件化开发、类型安全、社区活跃 |
| UI组件库 | Ant Design / Material-UI | 企业级UI组件、开箱即用 |
| 浏览器自动化 | Puppeteer / Playwright | 强大的浏览器控制能力,支持Chrome内核 |
| 状态管理 | Zustand / Redux Toolkit | 轻量级状态管理 |
| 进程通信 | Electron IPC | 主进程与渲染进程通信 |
| 打包工具 | electron-builder | 支持多平台打包、代码签名、自动更新 |
| 自动更新 | electron-updater | 与electron-builder无缝集成 |
| 代码保护 | ASAR加密 + Webpack混淆 | 防止代码被轻易反编译 |
┌─────────────────────────────────────────┐
│ Electron Main Process │
│ ┌────────────────────────────────────┐ │
│ │ - 窗口管理 (BrowserWindow) │ │
│ │ - 自动更新 (electron-updater) │ │
│ │ - 进程通信 (IPC Main) │ │
│ │ - 浏览器自动化控制 (Puppeteer) │ │
│ │ - Steam软件交互 │ │
│ │ - 本地存储与配置 │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────┘
↕ IPC通信
┌─────────────────────────────────────────┐
│ Electron Renderer Process │
│ ┌────────────────────────────────────┐ │
│ │ React Application │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ 登录页面 │ │ │
│ │ └──────────────────────────────┘ │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ 主界面 │ │ │
│ │ │ ├─ 顶部栏 (Logo/退出) │ │ │
│ │ │ ├─ 左侧菜单导航 │ │ │
│ │ │ └─ 右侧多Tab内容区 │ │ │
│ │ └──────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────┘
实现方案:
// 主进程:创建登录窗口
function createLoginWindow() {
const loginWindow = new BrowserWindow({
width: 400,
height: 500,
frame: false, // 无边框窗口
resizable: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
loginWindow.loadURL('login.html');
}
// 登录成功后创建主窗口
function createMainWindow() {
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 1000,
minHeight: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
mainWindow.loadURL('index.html');
}
界面布局:
优势:
实现步骤:
打包Chrome浏览器
// electron-builder配置
{
"extraResources": [
{
"from": "node_modules/puppeteer/.local-chromium/",
"to": "chromium",
"filter": ["**/*"]
}
]
}
async function launchBrowser() { const chromePath = path.join( process.resourcesPath, 'chromium', 'chrome.exe' );
const browser = await puppeteer.launch({ executablePath: chromePath, headless: false, // 可视化浏览器 defaultViewport: null, args: [ '--disable-web-security', '--disable-features=IsolateOrigins,site-per-process' ] });
return browser; } ```
自动化操作示例 ```typescript async function automateWebPage(url: string) { const browser = await launchBrowser(); const page = await browser.newPage();
await page.goto(url);
// 填充表单 await page.type('#username', 'user@example.com'); await page.type('#password', 'password123');
// 点击按钮 await page.click('button[type="submit"]');
// 等待导航 await page.waitForNavigation();
// 截图 await page.screenshot({ path: 'screenshot.png' });
await browser.close(); }
#### **方案B:使用Playwright(备选)**
**优势:**
- 支持多浏览器内核
- 更现代的API设计
- 更好的自动等待机制
```typescript
import { chromium } from 'playwright-core';
async function launchPlaywright() {
const browser = await chromium.launch({
executablePath: chromePath,
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
return { browser, page };
}
实现方案:
打包插件文件
// 将插件文件夹放入resources
{
"extraResources": [
{
"from": "chrome-extensions/",
"to": "extensions",
"filter": ["**/*"]
}
]
}
const browser = await puppeteer.launch({
headless: false,
args: [
--disable-extensions-except=${extensionPath},
--load-extension=${extensionPath}
]
});
```
实现方案:
// 打包SDA.exe到resources const sdaPath = path.join(process.resourcesPath, 'sda', 'SteamDesktopAuthenticator.exe');
// 调用SDA获取验证码 function getSteamGuardCode(username: string): Promise { return new Promise((resolve, reject) => {
const process = spawn(sdaPath, ['--user', username, '--get-code']);
let output = '';
process.stdout.on('data', (data) => {
output += data.toString();
});
process.on('close', (code) => {
if (code === 0) {
const code = output.trim();
resolve(code);
} else {
reject(new Error('Failed to get Steam Guard code'));
}
});
}); }
// 确认Steam交易 function confirmSteamTrade(tradeId: string): Promise { return new Promise((resolve, reject) => {
exec(`"${sdaPath}" --confirm-trade ${tradeId}`, (error, stdout) => {
if (error) {
reject(error);
} else {
resolve(stdout.includes('success'));
}
});
}); }
2. **方案B:读取SDA配置文件**
```typescript
import fs from 'fs';
import crypto from 'crypto';
// SDA的配置文件通常在用户目录
const sdaConfigPath = path.join(
process.env.APPDATA,
'SteamDesktopAuthenticator',
'maFiles'
);
// 读取账号配置
function readSDAConfig(username: string) {
const configFile = path.join(sdaConfigPath, `${username}.maFile`);
const data = fs.readFileSync(configFile, 'utf-8');
return JSON.parse(data);
}
// 生成验证码(需要实现Steam的TOTP算法)
function generateSteamGuardCode(sharedSecret: string): string {
// 实现Steam的Time-based OTP算法
// 参考SDA源码实现
const time = Math.floor(Date.now() / 1000);
const timeBuffer = Buffer.allocUnsafe(8);
timeBuffer.writeBigInt64BE(BigInt(Math.floor(time / 30)));
const hmac = crypto.createHmac('sha1', Buffer.from(sharedSecret, 'base64'));
hmac.update(timeBuffer);
const hash = hmac.digest();
// Steam字符集
const steamChars = '23456789BCDFGHJKMNPQRTVWXY';
let code = '';
// 生成5位验证码
const start = hash[19] & 0x0f;
const fullCode = hash.readUInt32BE(start) & 0x7fffffff;
for (let i = 0; i < 5; i++) {
code += steamChars[fullCode % steamChars.length];
}
return code;
}
// 渲染进程调用 const result = await window.electron.steam.getGuardCode('myusername'); if (result.success) { console.log('验证码:', result.code); }
### 3.6 自动更新功能
**实现方案:**
1. **配置electron-updater**
```javascript
// package.json
{
"build": {
"publish": [
{
"provider": "generic",
"url": "https://your-server.com/updates"
}
]
}
}
// 配置更新服务器 autoUpdater.setFeedURL({ provider: 'generic', url: 'https://your-server.com/updates' });
// 检查更新 autoUpdater.checkForUpdates();
// 监听更新事件 autoUpdater.on('update-available', (info) => { // 通知渲染进程有新版本 mainWindow.webContents.send('update:available', info); });
autoUpdater.on('update-downloaded', (info) => { // 下载完成,询问用户是否安装 mainWindow.webContents.send('update:downloaded', info); });
// 安装更新 ipcMain.on('update:install', () => { autoUpdater.quitAndInstall(); });
3. **渲染进程UI提示**
```typescript
// React组件
function UpdateNotification() {
const [updateInfo, setUpdateInfo] = useState(null);
useEffect(() => {
window.electron.on('update:available', (info) => {
notification.info({
message: '发现新版本',
description: `版本 ${info.version} 正在下载...`
});
});
window.electron.on('update:downloaded', (info) => {
Modal.confirm({
title: '更新已下载',
content: '是否立即重启安装新版本?',
onOk: () => {
window.electron.send('update:install');
}
});
});
}, []);
return null;
}
多层防护方案:
ASAR加密
// electron-builder配置
{
"asar": true,
"asarUnpack": ["**/*.node", "**/*.exe"],
"electronDownload": {
"mirror": "https://npm.taobao.org/mirrors/electron/"
}
}
module.exports = { optimization: { minimize: true, minimizer: [ new TerserPlugin({
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
},
mangle: true
}
}) ] }, plugins: [ new WebpackObfuscator({ rotateStringArray: true, stringArray: true, stringArrayThreshold: 0.75 }, []) ] }; ```
敏感代码原生化 ```typescript // 使用Node Native Addon(C++)保护核心逻辑 // 编译为.node二进制文件 const nativeModule = require('./build/Release/protection.node');
function validateLicense(key: string): boolean { return nativeModule.checkLicense(key); }
4. **许可证验证**
```typescript
import crypto from 'crypto';
// 硬件ID绑定
function getHardwareId(): string {
const os = require('os');
const cpuId = os.cpus()[0].model;
const macAddress = Object.values(os.networkInterfaces())
.flat()
.find(i => !i.internal && i.mac !== '00:00:00:00:00:00')?.mac;
return crypto
.createHash('sha256')
.update(cpuId + macAddress)
.digest('hex');
}
// 验证许可证
function validateLicense(licenseKey: string): boolean {
const hardwareId = getHardwareId();
const serverUrl = 'https://your-server.com/api/validate';
// 向服务器验证
return fetch(serverUrl, {
method: 'POST',
body: JSON.stringify({ licenseKey, hardwareId })
})
.then(res => res.json())
.then(data => data.valid);
}
function verifyIntegrity(): boolean { const appPath = app.getAppPath(); const checksumFile = path.join(appPath, 'checksums.json'); const checksums = JSON.parse(fs.readFileSync(checksumFile, 'utf-8'));
for (const [file, expectedHash] of Object.entries(checksums)) {
const filePath = path.join(appPath, file);
const content = fs.readFileSync(filePath);
const actualHash = crypto.createHash('sha256').update(content).digest('hex');
if (actualHash !== expectedHash) {
return false; // 文件被篡改
}
}
return true; }
// 应用启动时检查 app.on('ready', () => { if (!verifyIntegrity()) {
dialog.showErrorBox('安全警告', '检测到程序文件被篡改,无法启动!');
app.quit();
} });
### 3.8 窗口大小控制
```typescript
// 主进程:窗口控制API
ipcMain.handle('window:resize', (event, width, height) => {
const window = BrowserWindow.fromWebContents(event.sender);
window.setSize(width, height, true);
});
ipcMain.handle('window:maximize', (event) => {
const window = BrowserWindow.fromWebContents(event.sender);
if (window.isMaximized()) {
window.unmaximize();
} else {
window.maximize();
}
});
ipcMain.handle('window:minimize', (event) => {
const window = BrowserWindow.fromWebContents(event.sender);
window.minimize();
});
ipcMain.handle('window:setFullScreen', (event, flag) => {
const window = BrowserWindow.fromWebContents(event.sender);
window.setFullScreen(flag);
});
// 渲染进程:React组件
function WindowControls() {
const handleResize = (width: number, height: number) => {
window.electron.window.resize(width, height);
};
const handleMaximize = () => {
window.electron.window.maximize();
};
return (
<div className="window-controls">
<button onClick={() => handleResize(1024, 768)}>标准</button>
<button onClick={() => handleResize(1280, 720)}>宽屏</button>
<button onClick={() => handleResize(1920, 1080)}>全高清</button>
<button onClick={handleMaximize}>最大化</button>
</div>
);
}
buff-app/
├── package.json
├── tsconfig.json
├── webpack.config.js
├── electron-builder.json
├── src/
│ ├── main/ # 主进程代码
│ │ ├── index.ts # 主进程入口
│ │ ├── windows.ts # 窗口管理
│ │ ├── updater.ts # 自动更新
│ │ ├── browser-automation.ts # 浏览器自动化
│ │ ├── steam-integration.ts # Steam交互
│ │ ├── ipc-handlers.ts # IPC处理器
│ │ └── security.ts # 安全验证
│ ├── preload/ # 预加载脚本
│ │ └── index.ts
│ ├── renderer/ # 渲染进程(React)
│ │ ├── index.tsx
│ │ ├── App.tsx
│ │ ├── pages/ # 页面组件
│ │ │ ├── Login.tsx
│ │ │ ├── Dashboard.tsx
│ │ │ └── ...
│ │ ├── components/ # 通用组件
│ │ │ ├── Layout/
│ │ │ ├── Header/
│ │ │ ├── Sidebar/
│ │ │ └── TabView/
│ │ ├── store/ # 状态管理
│ │ └── utils/ # 工具函数
│ └── common/ # 共享代码
│ ├── types.ts
│ └── constants.ts
├── resources/ # 资源文件
│ ├── chromium/ # Chrome浏览器
│ ├── extensions/ # Chrome插件
│ ├── sda/ # Steam Desktop Authenticator
│ └── icons/ # 应用图标
└── dist/ # 构建输出
总开发周期:8-12周
问题: Chromium完整包约300-500MB
解决方案:
问题: 某些插件可能不兼容自动化浏览器
解决方案:
问题: SDA是独立应用,需要进程间通信
解决方案:
问题: Electron应用容易被反编译
解决方案:
问题: 更新失败可能导致应用无法启动
解决方案:
{
"name": "buff-app",
"version": "1.0.0",
"build": {
"appId": "com.yourcompany.buffapp",
"productName": "Buff App",
"copyright": "Copyright © 2025",
"directories": {
"output": "dist",
"buildResources": "resources"
},
"files": [
"dist/**/*",
"package.json"
],
"win": {
"target": [
{
"target": "nsis",
"arch": ["x64", "ia32"]
}
],
"icon": "resources/icons/icon.ico",
"requestedExecutionLevel": "asInvoker"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"perMachine": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "Buff App"
},
"extraResources": [
{
"from": "resources/chromium",
"to": "chromium"
},
{
"from": "resources/extensions",
"to": "extensions"
},
{
"from": "resources/sda",
"to": "sda"
}
],
"publish": {
"provider": "generic",
"url": "https://your-server.com/updates"
}
}
}
Windows代码签名:
# 获取代码签名证书(EV或OV证书)
# 配置electron-builder
{
"win": {
"certificateFile": "cert.pfx",
"certificatePassword": "your-password",
"signingHashAlgorithms": ["sha256"],
"sign": "./sign.js" // 自定义签名脚本
}
}
最低配置:
推荐配置:
| 风险项 | 概率 | 影响 | 应对措施 |
|---|---|---|---|
| Chrome打包体积过大 | 高 | 中 | 使用Electron内置Chromium或在线下载 |
| SDA集成困难 | 中 | 高 | 预研SDA API,准备备用方案 |
| 防破解被突破 | 中 | 高 | 多层防护+服务端验证 |
| Windows版本兼容性 | 低 | 中 | 多版本测试,使用兼容API |
| 自动更新失败 | 低 | 中 | 实现回滚机制,提供手动更新 |
| 性能问题 | 中 | 中 | 代码优化,异步处理,懒加载 |
技术栈:
优势:
劣势:
技术栈:
优势:
劣势:
文档版本: v1.0
创建日期: 2025-10-19
最后更新: 2025-10-19