Files
autoAiWorkSys/_doc/发布的接口文档.md
张成 0e334116b6 1
2025-11-28 09:50:38 +08:00

575 lines
15 KiB
Markdown
Raw 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.
# 发布脚本使用说明
## 📋 概述
发布脚本 (`scripts/publish.js`) 用于自动化应用的构建和发布流程,包括:
1. 清理构建目录
2. 构建应用NSIS 或便携版)
3. 调用接口创建版本记录
4. 上传压缩包到 OSS
## 🚀 快速开始
### 安装依赖
确保已安装 `form-data` 依赖:
```bash
npm install form-data --save-dev
```
### 基本使用
```bash
# 发布 NSIS 安装包(默认)
npm run publish
# 或直接运行脚本
node scripts/publish.js
```
## 📝 命令选项
### 构建类型
```bash
# 发布 NSIS 安装包
npm run publish:nsis
# 或
node scripts/publish.js --type nsis
# 发布便携版
npm run publish:portable
# 或
node scripts/publish.js --type portable
```
### 发布说明
```bash
node scripts/publish.js --notes "修复了若干bug优化了性能"
```
### 强制更新
```bash
node scripts/publish.js --force
```
### 跳过步骤
```bash
# 仅上传已构建的文件(跳过构建)
node scripts/publish.js --skip-build
# 仅构建不上传
node scripts/publish.js --skip-upload
```
### 查看帮助
```bash
node scripts/publish.js --help
```
## 🔧 配置要求
### 1. 配置文件
确保 `config/appConfig.js` 中包含有效的配置:
```javascript
module.exports = {
api_urls: {
dev: "http://work.light120.com/api",
prod: "http://work.light120.com/api"
},
token: "your-token-here", // 必须配置有效的 token
// ...
};
```
### 2. API 接口
脚本需要以下 API 接口:
#### 接口 1创建版本记录
- **接口地址**: `POST /api/version/create`
- **请求头**:
```
Content-Type: application/json
Authorization: Bearer ${token}
```
- **请求参数**:
```json
{
"version": "1.0.0", // 必填版本号x.y.z 格式)
"platform": "win32", // 必填平台类型win32/darwin/linux
"arch": "x64", // 必填架构类型x64/ia32/arm64
"download_url": "https://...", // 必填:下载地址(上传后更新)
"file_path": "/path/to/file", // 必填:服务器文件路径
"file_size": 12345678, // 可选:文件大小(字节),不提供会自动计算
"file_hash": "sha256-hash", // 可选SHA256 哈希值,不提供会自动计算
"release_notes": "发布说明", // 可选:更新日志
"force_update": 0, // 可选是否强制更新1:是 0:否),默认 0
"status": 1 // 可选状态1:启用 0:禁用),默认 1
}
```
- **响应示例**:
```json
{
"code": 0,
"message": "版本创建成功",
"data": {
"id": 123,
"version": "1.0.0",
"platform": "win32",
"arch": "x64",
"download_url": "https://oss.example.com/path/to/file.exe",
"file_path": "/path/to/file.exe",
"file_size": 12345678,
"file_hash": "sha256-hash-value",
"release_notes": "发布说明",
"force_update": 0,
"status": 1,
"create_time": "2024-01-01 12:00:00"
}
}
```
- **错误响应**:
```json
{
"code": 400,
"message": "版本号不能为空" // 或其他错误信息
}
```
- **注意事项**:
- 版本号格式必须为 `x.y.z`1.0.0
- 平台类型必须为:`win32`、`darwin` 或 `linux`
- 架构类型必须为:`x64`、`ia32` 或 `arm64`
- 如果版本已存在(相同 version + platform + arch会返回错误
- 如果提供了 `file_path` 但未提供 `file_size` 或 `file_hash`,接口会自动计算
#### 接口 2上传文件到 OSS
- **接口地址**: `POST /api/file/upload_version`
- **请求头**:
```
Content-Type: multipart/form-data
Authorization: Bearer ${token}
```
- **请求参数**Form Data:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `file` | File | 是 | 文件内容(二进制) |
| `version` | String | 是 | 版本号1.0.0 |
| `platform` | String | 是 | 平台类型win32/darwin/linux |
| `arch` | String | 是 | 架构类型x64/ia32/arm64 |
| `file_hash` | String | 是 | SHA256 哈希值 |
| `file_size` | Number | 是 | 文件大小(字节) |
| `version_id` | Number | 否 | 版本记录 ID如果已创建版本记录 |
| `build_type` | String | 否 | 构建类型nsis/portable |
- **请求示例**(使用 form-data:
```javascript
const FormData = require('form-data');
const fs = require('fs');
const form = new FormData();
form.append('file', fs.createReadStream('./dist/app.exe'));
form.append('version', '1.0.0');
form.append('platform', 'win32');
form.append('arch', 'x64');
form.append('file_hash', 'sha256-hash-value');
form.append('file_size', 12345678);
form.append('version_id', 123); // 可选
// 发送请求
form.submit('http://api.example.com/api/file/upload_version', {
headers: {
'Authorization': `Bearer ${token}`
}
}, callback);
```
- **响应示例**:
```json
{
"code": 0,
"message": "文件上传成功",
"data": {
"download_url": "https://oss.example.com/versions/win32/x64/app-1.0.0.exe",
"file_path": "versions/win32/x64/app-1.0.0.exe",
"oss_path": "https://oss.example.com/versions/win32/x64/app-1.0.0.exe",
"file_size": 12345678,
"file_hash": "sha256-hash-value"
}
}
```
- **错误响应**:
```json
{
"code": 400,
"message": "文件上传失败:文件大小不匹配" // 或其他错误信息
}
```
- **注意事项**:
- 文件会按照 `versions/{platform}/{arch}/{filename}` 的路径结构上传到 OSS
- 上传前会验证文件哈希值,确保文件完整性
- 上传成功后,建议调用 `/version/update` 接口更新版本记录的下载地址
- 大文件上传建议设置较长的超时时间(建议 10 分钟以上)
#### 接口 3更新版本下载地址可选
- **接口地址**: `POST /api/version/update`
- **请求头**:
```
Content-Type: application/json
Authorization: Bearer ${token}
```
- **请求参数**:
```json
{
"id": 123, // 必填:版本记录 ID
"download_url": "https://...", // 可选:下载地址
"file_path": "/path/to/file", // 可选:文件路径
"file_hash": "sha256-hash", // 可选:文件哈希值
"file_size": 12345678, // 可选:文件大小
"release_notes": "更新说明", // 可选:更新日志
"force_update": 1, // 可选:是否强制更新
"status": 1 // 可选:状态
}
```
- **响应示例**:
```json
{
"code": 0,
"message": "版本更新成功",
"data": {
"id": 123,
"version": "1.0.0",
"download_url": "https://oss.example.com/path/to/file.exe",
// ... 其他字段
}
}
```
- **使用场景**:
- 文件上传成功后,更新版本记录的下载地址
- 修改版本的发布说明或强制更新标志
- 启用或禁用某个版本
## 📦 发布流程
1. **清理构建目录**
- 删除 `dist` 目录及其所有内容
2. **构建应用**
- 根据构建类型执行 `electron-builder`
- NSIS: `electron-builder --win nsis`
- Portable: `electron-builder --win portable`
3. **查找构建产物**
- 在 `dist` 目录中查找 `.exe` 文件
- 按文件大小排序,优先处理主安装包
4. **创建版本记录**
- 调用 `POST /api/version/create` 接口
- 传递版本信息、平台、架构等
- 获取版本记录 ID用于后续更新
5. **上传文件到 OSS**
- 计算文件 SHA256 哈希值
- 使用 `multipart/form-data` 格式调用 `POST /api/file/upload_version` 接口
- 传递文件、版本信息、哈希值等参数
- 获取上传后的下载地址
6. **更新版本记录**
- 使用获取到的下载地址调用 `POST /api/version/update` 接口
- 更新版本记录的 `download_url` 和 `file_path` 字段
## ⚠️ 注意事项
1. **Token 配置**
- 确保 `config/appConfig.js` 中有有效的 `token`
- Token 用于 API 认证,格式为 `Bearer ${token}`
- 所有接口请求都需要在请求头中包含 `Authorization: Bearer ${token}`
2. **接口路径**
- 所有接口路径前缀为 `/api`
- 完整路径示例:
- 创建版本:`POST http://api.example.com/api/version/create`
- 上传文件:`POST http://api.example.com/api/file/upload_version`
- 更新版本:`POST http://api.example.com/api/version/update`
3. **文件大小**
- 大文件上传可能需要较长时间
- 脚本默认超时时间为 10 分钟600000ms
- 建议大文件(>100MB增加超时时间到 30 分钟
4. **网络连接**
- 确保能够访问 API 服务器和 OSS
- 上传大文件时建议使用稳定的网络连接
- 建议在网络稳定的环境下执行发布流程
5. **版本号**
- 版本号从 `package.json` 的 `version` 字段读取
- 发布前确保版本号已更新
- 版本号格式必须符合 `x.y.z` 格式1.0.0
6. **构建产物**
- 脚本会自动查找 `dist` 目录中的 `.exe` 文件
- 排除 `builder` 和 `helper` 相关的辅助文件
- 确保构建产物文件名清晰,便于识别
7. **文件哈希验证**
- 上传前必须计算文件的 SHA256 哈希值
- 上传接口会验证文件哈希,确保文件完整性
- 哈希值不匹配会导致上传失败
8. **接口调用顺序**
- 建议先创建版本记录(获取 version_id
- 然后上传文件(可传递 version_id
- 最后更新版本记录的下载地址
- 也可以先上传文件,再创建版本记录并更新下载地址
## 🔍 故障排查
### 问题:上传失败
**可能原因**:
- Token 无效或过期
- API 接口地址不正确
- 网络连接问题
- 文件过大,超时
**解决方法**:
1. 检查 `config/appConfig.js` 中的 `token` 是否有效
2. 检查 API 地址是否正确
3. 检查网络连接
4. 如果文件很大,可以增加超时时间
### 问题:构建失败
**可能原因**:
- 缺少依赖
- electron-builder 配置错误
- 磁盘空间不足
**解决方法**:
1. 运行 `npm install` 安装所有依赖
2. 检查 `package.json` 中的 `build` 配置
3. 确保有足够的磁盘空间
### 问题:找不到构建产物
**可能原因**:
- 构建未成功完成
- 构建产物在其他位置
**解决方法**:
1. 检查构建日志,确认构建成功
2. 手动检查 `dist` 目录
3. 使用 `--skip-build` 选项,手动指定文件路径(需要修改脚本)
## 📝 示例
### 完整发布流程
```bash
# 1. 更新版本号(在 package.json 中)
# "version": "1.0.1"
# 2. 发布
npm run publish -- --notes "新功能:支持自动投递简历" --force
```
### 仅上传已构建的文件
```bash
# 1. 手动构建
npm run build:nsis
# 2. 仅上传
node scripts/publish.js --skip-build
```
### 测试发布(不上传)
```bash
# 构建并创建版本记录,但不上传文件
node scripts/publish.js --skip-upload
```
## 💻 接口调用示例
### Node.js 示例代码
#### 1. 创建版本记录
```javascript
const axios = require('axios');
const crypto = require('crypto');
const fs = require('fs');
async function createVersion() {
const filePath = './dist/app-1.0.0.exe';
const stats = fs.statSync(filePath);
const fileSize = stats.size;
// 计算文件哈希
const fileBuffer = fs.readFileSync(filePath);
const fileHash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
const response = await axios.post('http://api.example.com/api/version/create', {
version: '1.0.0',
platform: 'win32',
arch: 'x64',
download_url: '', // 上传后更新
file_path: filePath,
file_size: fileSize,
file_hash: fileHash,
release_notes: '修复了若干bug优化了性能',
force_update: 0,
status: 1
}, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return response.data.data; // 返回版本记录,包含 id
}
```
#### 2. 上传文件到 OSS
```javascript
const FormData = require('form-data');
const axios = require('axios');
const fs = require('fs');
const crypto = require('crypto');
async function uploadVersionFile(versionId) {
const filePath = './dist/app-1.0.0.exe';
const stats = fs.statSync(filePath);
const fileSize = stats.size;
// 计算文件哈希
const fileBuffer = fs.readFileSync(filePath);
const fileHash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
// 创建 FormData
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
form.append('version', '1.0.0');
form.append('platform', 'win32');
form.append('arch', 'x64');
form.append('file_hash', fileHash);
form.append('file_size', fileSize);
if (versionId) {
form.append('version_id', versionId);
}
const response = await axios.post('http://api.example.com/api/file/upload_version', form, {
headers: {
'Authorization': `Bearer ${token}`,
...form.getHeaders()
},
maxContentLength: Infinity,
maxBodyLength: Infinity,
timeout: 600000 // 10 分钟超时
});
return response.data.data; // 返回上传结果,包含 download_url
}
```
#### 3. 更新版本下载地址
```javascript
async function updateVersionDownloadUrl(versionId, downloadUrl, fileHash) {
const response = await axios.post('http://api.example.com/api/version/update', {
id: versionId,
download_url: downloadUrl,
file_hash: fileHash
}, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return response.data.data;
}
```
#### 4. 完整发布流程示例
```javascript
async function publishVersion() {
try {
// 1. 创建版本记录
console.log('创建版本记录...');
const version = await createVersion();
console.log('版本记录创建成功ID:', version.id);
// 2. 上传文件
console.log('上传文件到 OSS...');
const uploadResult = await uploadVersionFile(version.id);
console.log('文件上传成功,下载地址:', uploadResult.download_url);
// 3. 更新版本下载地址
console.log('更新版本下载地址...');
await updateVersionDownloadUrl(version.id, uploadResult.download_url, uploadResult.file_hash);
console.log('版本发布完成!');
} catch (error) {
console.error('发布失败:', error.response?.data || error.message);
throw error;
}
}
```
### cURL 示例
#### 创建版本记录
```bash
curl -X POST http://api.example.com/api/version/create \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{
"version": "1.0.0",
"platform": "win32",
"arch": "x64",
"download_url": "",
"file_path": "/path/to/file.exe",
"file_size": 12345678,
"file_hash": "sha256-hash-value",
"release_notes": "发布说明",
"force_update": 0,
"status": 1
}'
```
#### 上传文件
```bash
curl -X POST http://api.example.com/api/file/upload_version \
-H "Authorization: Bearer your-token-here" \
-F "file=@./dist/app-1.0.0.exe" \
-F "version=1.0.0" \
-F "platform=win32" \
-F "arch=x64" \
-F "file_hash=sha256-hash-value" \
-F "file_size=12345678" \
-F "version_id=123"
```
## 🔗 相关文档
- [API 配置说明](./API_CONFIG.md)
- [打包说明](./BUILD.md)
- [更新逻辑检查报告](./更新逻辑检查报告.md)