Files
CN_Tool_client/doc/开发者指南_自己动手修改.md
2026-04-13 17:32:58 +08:00

570 lines
13 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.

# 开发者指南 - 自己动手修改代码
本指南说明我帮您创建的所有文件、它们的作用,以及如何自己修改和调试。
---
## 📁 我创建的文件清单
### 1. 核心脚本scripts/ 目录)
#### `scripts/port-checker.js` - 端口检测工具
**作用**:检测端口是否可用,找到可用端口
**关键方法**
```javascript
PortChecker.checkPort(3306) // 检查单个端口
PortChecker.findAvailablePort(3306) // 从3306开始找可用端口
PortChecker.waitForPort(3306) // 等待端口开始监听
```
**如何修改**
- 修改端口检测范围:改 `maxAttempts` 参数默认100
- 修改超时时间:改 `waitForPort``timeout` 参数默认30秒
**调试方法**
```javascript
// 单独测试
const PortChecker = require('./port-checker');
PortChecker.checkPort(3306).then(console.log);
```
---
#### `scripts/startup-manager.js` - 启动状态管理器
**作用**管理Loading窗口显示启动进度
**关键方法**
```javascript
startupManager.createLoadingWindow() // 创建Loading窗口
startupManager.updateProgress('init') // 更新进度
startupManager.showError('错误信息') // 显示错误
startupManager.closeLoadingWindow() // 关闭Loading窗口
```
**如何修改启动步骤**
在构造函数中修改 `this.steps` 数组:
```javascript
this.steps = [
{ id: 'init', label: '正在初始化应用...', progress: 0 },
{ id: 'check-mysql-port', label: '正在检测MySQL端口...', progress: 15 },
// ... 添加或修改步骤
];
```
**调试方法**
```javascript
// 在 lifecycle.js 中添加日志
console.log('[StartupManager] Current step:', this.getCurrentStep());
```
---
#### `scripts/config-generator.js` - 配置文件生成器
**作用**根据实际路径和端口生成Spring Boot配置文件
**关键方法**
```javascript
configGenerator.generateConfig({
mysqlPort: 3306,
javaPort: 18092
})
```
**如何修改数据目录位置**
修改 `getDataPath` 方法:
```javascript
getDataPath(baseDir) {
const driveLetter = path.parse(baseDir).root;
// 改成你想要的路径
return path.join(driveLetter, 'YourCustomPath');
}
```
**如何添加更多占位符**
1.`application.yml.template` 中添加占位符:`{{YOUR_PLACEHOLDER}}`
2.`generateConfig` 方法中添加替换逻辑:
```javascript
template = template.replace(/{{YOUR_PLACEHOLDER}}/g, yourValue);
```
**调试方法**
```javascript
// 单独测试
const ConfigGenerator = require('./scripts/config-generator');
const gen = new ConfigGenerator();
gen.generateConfig({ mysqlPort: 3307 }).then(console.log);
```
---
#### `scripts/mysql-process-manager.js` - MySQL 进程管理器(绿色包 - 进程模式)
**作用**:以进程模式管理 MySQL**无需管理员权限**,随应用启动/关闭
**核心方法**
```javascript
// 主要方法:
ensureServiceRunning() // 确保 MySQL 运行(主流程)
startMySQLProcess(port) // 启动 MySQL 进程
stopMySQLProcess() // 停止 MySQL 进程
checkAndKillOrphanProcess() // 清理残留进程
isMySQLRunning() // 检查进程是否运行
```
**如何修改 my.ini 配置**
`generateMyIni` 方法中修改配置模板:
```javascript
generateMyIni(port) {
const config = `[mysqld]
basedir=${basedir}
datadir=${datadir}
port=${port}
bind-address=0.0.0.0
character-set-server=utf8mb4
max_connections=500 # 修改最大连接数
innodb_buffer_pool_size=256M # 修改缓冲池大小
`;
// ...
}
```
**如何修改启动参数**
`startMySQLProcess` 方法中修改 spawn 参数:
```javascript
this.mysqlProcess = spawn(mysqldPath, [
`--defaults-file=${this.configFile}`,
'--console',
'--skip-grant-tables', // 添加跳过权限检查(仅用于调试)
], {
cwd: this.binPath,
stdio: ['ignore', 'pipe', 'pipe']
});
```
**调试方法**
```javascript
// 单独测试
const MySQLProcessManager = require('./scripts/mysql-process-manager');
const mysql = new MySQLProcessManager();
mysql.ensureServiceRunning(
(startPort, maxAttempts) => startPort, // Mock port checker
(port, timeout) => Promise.resolve(true)
).then(port => {
console.log('MySQL started on port:', port);
});
```
---
#### `scripts/java-runner.js` - Java 运行器
**作用**运行Spring Boot JAR文件
**关键修改**
```javascript
// 我添加的:
runSpringBoot(jarPath, configPath) // 运行Spring Boot
stopSpringBoot() // 停止Spring Boot
```
**如何添加JVM参数**
`runSpringBoot` 方法中修改 `javaArgs`
```javascript
const javaArgs = [
'-Xms512m', // 最小堆内存
'-Xmx1024m', // 最大堆内存
'-Dfile.encoding=UTF-8', // 文件编码
'-jar',
jarPath,
`--spring.config.location=${configPath}`
];
```
**调试方法**
```javascript
// 单独测试
const JavaRunner = require('./scripts/java-runner');
const runner = new JavaRunner();
runner.runSpringBoot('path/to/jar', 'path/to/config');
```
---
### 2. 生命周期管理
#### `electron/preload/lifecycle.js` - 核心启动流程
**作用**:协调整个启动流程
**关键流程**
```javascript
ready() -> startApplication() -> {
1. 检测MySQL端口
2. 启动MySQL
3. 检测Java端口
4. 生成配置文件
5. 启动Spring Boot
}
```
**如何修改启动顺序**
`startApplication` 方法中调整步骤顺序或添加新步骤:
```javascript
async startApplication() {
// 步骤1: 初始化
this.startupManager.updateProgress('init');
// 添加你的自定义步骤
this.startupManager.updateProgress('custom-step');
await this.yourCustomFunction();
// 继续原有步骤...
}
```
**如何修改超时时间**
```javascript
// MySQL等待超时
const mysqlReady = await PortChecker.waitForPort(actualPort, 30000); // 改这里
// Java等待超时
const javaReady = await PortChecker.waitForPort(this.javaPort, 60000); // 改这里
```
**调试方法**
在关键位置添加日志:
```javascript
logger.info('[lifecycle] 当前步骤:', stepName);
console.log('[DEBUG] 端口:', this.mysqlPort, this.javaPort);
```
---
### 3. UI 界面
#### `public/html/loading.html` - Loading 界面
**作用**:显示启动进度的美观界面
**如何修改样式**
修改 `<style>` 标签内的CSS
```css
/* 修改背景颜色 */
.loading-container {
background: linear-gradient(135deg, #your-color-1 0%, #your-color-2 100%);
}
/* 修改进度条颜色 */
.progress-bar {
background: linear-gradient(90deg, #your-color 0%, #your-color 100%);
}
```
**如何修改文字内容**
修改 `<div>` 标签内的文字:
```html
<div class="logo">您的应用名称</div>
<div class="subtitle">您的公司名称</div>
```
**如何添加更多显示信息**
1. 在HTML中添加元素
```html
<div class="custom-info" id="customInfo"></div>
```
2. 在JavaScript中更新
```javascript
ipcRenderer.on('startup-progress', (event, data) => {
if (data.customData) {
document.getElementById('customInfo').textContent = data.customData;
}
});
```
---
### 4. 配置文件
#### `build/extraResources/java/application.yml.template` - 配置模板
**作用**Spring Boot配置文件模板运行时生成实际配置
**占位符说明**
- `{{APP_DATA_PATH}}` - 会被替换为实际数据目录路径
- `localhost:3306` - 会被替换为实际MySQL端口
- `port: 18092` - 会被替换为实际Java端口
**如何添加新的配置项**
1. 在模板中添加配置:
```yaml
your-config:
value: {{YOUR_VALUE}}
```
2.`config-generator.js` 中添加替换:
```javascript
template = template.replace(/{{YOUR_VALUE}}/g, yourActualValue);
```
---
## 🔧 常见修改场景
### 场景1修改端口检测起始值
**文件**`electron/preload/lifecycle.js`
**修改**
```javascript
// 原代码
this.mysqlPort = await PortChecker.findAvailablePort(3306, 100);
// 改为从3310开始
this.mysqlPort = await PortChecker.findAvailablePort(3310, 100);
```
---
### 场景2修改数据目录位置
**文件**`scripts/config-generator.js`
**修改**
```javascript
getDataPath(baseDir) {
// 原代码:使用盘符根目录
// const driveLetter = path.parse(baseDir).root;
// return path.join(driveLetter, 'CN_Tool_Data');
// 改为:使用应用同级目录
return path.join(baseDir, 'Data');
// 或者:使用固定路径
return 'C:\\MyCustomPath\\Data';
}
```
---
### 场景3修改Loading步骤
**文件**`scripts/startup-manager.js`
**修改**
```javascript
this.steps = [
{ id: 'init', label: '正在初始化应用...', progress: 0 },
{ id: 'check-env', label: '正在检测环境...', progress: 10 }, // 新增
{ id: 'check-mysql-port', label: '正在检测MySQL端口...', progress: 20 },
// ... 调整其他步骤的进度值
];
```
然后在 `lifecycle.js` 中调用:
```javascript
this.startupManager.updateProgress('check-env');
await this.checkEnvironment(); // 你的自定义方法
```
---
### 场景4修改MySQL进程配置绿色包 - 进程模式)
**文件**`scripts/mysql-process-manager.js`
**修改 my.ini 配置**(推荐方式):
```javascript
generateMyIni(port) {
const config = `[mysqld]
basedir=${basedir}
datadir=${datadir}
port=${port}
# 网络配置
bind-address=0.0.0.0
max_connections=1000 # 增加最大连接数
# 性能优化
innodb_buffer_pool_size=256M # 设置缓冲池大小
innodb_log_file_size=128M # 增加日志文件大小
# 日志配置
log-error=mysql_error.log # 错误日志
slow_query_log=1 # 开启慢查询日志
slow_query_log_file=slow.log
long_query_time=2 # 慢查询阈值2秒
`;
// ...
}
```
**注意**:不要直接修改 spawn 参数,而是通过 my.ini 配置文件控制 MySQL 行为
---
### 场景5修改JVM内存
**文件**`scripts/java-runner.js`
**修改**
```javascript
runSpringBoot(jarPath, configPath, options = {}) {
const javaArgs = [
'-Xms1024m', // 最小堆内存 1GB
'-Xmx2048m', // 最大堆内存 2GB
'-XX:+UseG1GC', // 使用G1垃圾回收器
'-jar',
jarPath,
`--spring.config.location=${configPath}`
];
// ... rest of code
}
```
---
## 🐛 调试技巧
### 1. 查看日志
**日志位置**
```
C:\Users\[用户名]\AppData\Roaming\CN_Tool\logs\
├── 9100-YYYYMMDD.log # 应用日志
├── 9100-core-YYYYMMDD.log # 核心日志
└── 9100-error-YYYYMMDD.log # 错误日志
```
**如何添加日志**
```javascript
const { logger } = require('ee-core/log');
logger.info('[YourModule] 信息日志');
logger.warn('[YourModule] 警告日志');
logger.error('[YourModule] 错误日志');
```
---
### 2. 开发环境测试
**启动开发模式**
```bash
npm run dev
```
这样修改代码后可以立即看到效果,无需打包。
---
### 3. 单独测试模块
**创建测试文件** `test-my-module.js`
```javascript
const PortChecker = require('./scripts/port-checker');
async function test() {
console.log('测试端口检测...');
const port = await PortChecker.findAvailablePort(3306);
console.log('可用端口:', port);
}
test();
```
**运行测试**
```bash
node test-my-module.js
```
---
### 4. 调试Loading界面
**单独打开Loading页面**
```bash
# 在浏览器中直接打开
start public/html/loading.html
```
**模拟进度更新**
在浏览器控制台中:
```javascript
// 模拟进度更新
const event = new CustomEvent('startup-progress');
const data = { progress: 50, label: '测试进度...' };
// 需要调整代码来测试
```
---
## 📚 文件依赖关系
```
electron/preload/lifecycle.js (启动入口)
↓ 调用
├── scripts/startup-manager.js (显示Loading)
│ ↓ 使用
│ public/html/loading.html (Loading界面)
├── scripts/port-checker.js (检测端口)
├── scripts/mysql-process-manager.js (MySQL进程管理)
├── scripts/config-generator.js (生成配置)
│ ↓ 读取
│ build/extraResources/java/application.yml.template
└── scripts/java-runner.js (启动Java)
```
---
## 🎯 快速修改检查清单
修改代码后,检查这些点:
- [ ] 语法是否正确(运行 `npm run dev` 检查)
- [ ] 路径是否正确(注意 Windows 反斜杠)
- [ ] 日志是否添加(方便调试)
- [ ] 错误处理是否完善try-catch
- [ ] 注释是否清晰(方便后续维护)
---
## 💡 开发建议
1. **先在开发模式测试**
- 修改代码 → `npm run dev` → 测试
- 确认没问题后再打包
2. **保留备份**
- 修改前备份原文件
- 使用 Git 版本控制
3. **逐步修改**
- 一次只改一个功能
- 改完测试,确认无误再继续
4. **参考现有代码**
- 我写的代码都有详细注释
- 可以参考修改
5. **善用日志**
- 关键位置都加日志
- 出问题时方便定位
---
## 📞 代码位置速查
| 功能 | 文件 | 行数范围 |
|------|------|---------|
| 端口检测 | `scripts/port-checker.js` | 全文 |
| 启动管理 | `scripts/startup-manager.js` | 全文 |
| MySQL进程管理 | `scripts/mysql-process-manager.js` | 核心方法 ensureServiceRunning |
| Java启动 | `scripts/java-runner.js` | 152-198 |
| 配置生成 | `scripts/config-generator.js` | 38-83 |
| 启动流程 | `electron/preload/lifecycle.js` | 27-159 |
| Loading界面 | `public/html/loading.html` | 全文 |
---
南京灿能电气自动化有限公司
2025-10-15