# 服务端升级功能逻辑说明

## 概述

本文档说明服务端需要实现的升级功能逻辑，配合客户端的自动升级功能。

## API 接口要求

### GET /version/check

**功能**：检查是否有新版本可用

**请求参数**（Query 参数）：
- `current_version`: 当前版本号（x.y.z 格式，如 "1.0.0"）
- `platform`: 平台类型（如 "win32", "darwin", "linux"）
- `arch`: 架构类型（如 "x64", "ia32", "arm64"）
- `sn_code`: 设备序列号（可选，用于权限控制）

**响应格式**：
```json
{
  "code": 0,
  "message": "success",
  "data": {
    "version": "1.1.0",
    "download_url": "http://work.light120.com/downloads/app-1.1.0.exe",
    "release_notes": "修复了一些bug，新增了xxx功能",
    "force_update": false,
    "file_size": 52428800,
    "file_hash": "abc123def456..."
  }
}
```

**字段说明**：
- `version`: 最新版本号（x.y.z 格式）
- `download_url`: 更新包下载地址（完整的 HTTP/HTTPS URL）
- `release_notes`: 更新日志（可选，字符串）
- `force_update`: 是否强制更新（可选，布尔值，默认 false）
- `file_size`: 文件大小（字节，可选）
- `file_hash`: 文件 SHA256 哈希值（可选，用于校验文件完整性）

**业务逻辑**：

1. **版本比较**：
   - 从数据库查询最新版本信息（根据 platform 和 arch）
   - 比较请求中的 `current_version` 与数据库中的最新版本
   - 如果最新版本 > 当前版本，返回更新信息
   - 如果版本相同或更旧，返回 `code: 0, data: null` 或提示"已是最新版本"

2. **版本号格式**：
   - 格式：x.y.z（如 1.0.0, 1.1.0, 2.0.0）
   - 比较规则：主版本号 > 次版本号 > 修订号
   - 示例：1.1.0 > 1.0.0, 2.0.0 > 1.9.9

3. **平台和架构过滤**：
   - 只返回匹配 platform 和 arch 的版本信息
   - 如果某个平台没有新版本，返回空结果

4. **序列号验证**（可选）：
   - 可以根据 sn_code 验证设备权限
   - 如果启用权限控制，未授权的设备返回错误

5. **错误处理**：
   - 参数缺失：返回 `code: 400, message: "参数错误"`
   - 服务器错误：返回 `code: 500, message: "服务器错误"`
   - 无新版本：返回 `code: 0, data: null` 或 `has_update: false`

## 数据库设计建议

### 版本信息表（version_info）

| 字段名 | 类型 | 说明 | 约束 |
|--------|------|------|------|
| id | INT/BIGINT | 主键 | PRIMARY KEY, AUTO_INCREMENT |
| version | VARCHAR(20) | 版本号（x.y.z 格式） | NOT NULL, UNIQUE |
| platform | VARCHAR(20) | 平台类型（win32/darwin/linux） | NOT NULL |
| arch | VARCHAR(20) | 架构类型（x64/ia32/arm64） | NOT NULL |
| download_url | VARCHAR(500) | 下载地址 | NOT NULL |
| file_path | VARCHAR(500) | 服务器文件路径 | NOT NULL |
| file_size | BIGINT | 文件大小（字节） | DEFAULT 0 |
| file_hash | VARCHAR(64) | SHA256 哈希值 | |
| release_notes | TEXT | 更新日志 | |
| force_update | TINYINT(1) | 是否强制更新 | DEFAULT 0 |
| status | TINYINT(1) | 状态（1:启用 0:禁用） | DEFAULT 1 |
| create_time | DATETIME | 创建时间 | NOT NULL, DEFAULT CURRENT_TIMESTAMP |
| last_modify_time | DATETIME | 最后修改时间 | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |

**索引建议**：
- PRIMARY KEY (id)
- UNIQUE KEY (version, platform, arch)
- INDEX (platform, arch, status)

### 版本发布历史表（version_history）（可选）

用于记录版本发布历史，便于管理：

| 字段名 | 类型 | 说明 |
|--------|------|------|
| id | INT/BIGINT | 主键 |
| version_id | INT | 关联 version_info.id |
| release_type | VARCHAR(20) | 发布类型（stable/beta/alpha） |
| create_time | DATETIME | 发布时间 |
| last_modify_time | DATETIME | 最后修改时间 |

## 业务逻辑流程

### 1. 版本检查流程

```
客户端请求
  ↓
接收参数（current_version, platform, arch, sn_code）
  ↓
验证参数有效性
  ↓
查询数据库最新版本（按 platform + arch + status=1）
  ↓
版本号比较
  ↓
有更新？
  ├─ 是 → 构建返回数据（包含文件信息）
  └─ 否 → 返回空结果或提示"已是最新版本"
  ↓
返回响应
```

### 2. 版本管理流程

**新增版本**：
1. 上传安装包文件到服务器指定目录
2. 计算文件 SHA256 哈希值
3. 获取文件大小
4. 插入数据库记录（status=1 表示启用）

**禁用版本**：
1. 更新 status=0（不删除记录，保留历史）

**删除版本**：
1. 删除数据库记录
2. 删除服务器上的文件

### 3. 文件存储建议

**目录结构**：
```
/uploads/
  └── versions/
      ├── win32/
      │   ├── x64/
      │   │   ├── app-1.0.0.exe
      │   │   └── app-1.1.0.exe
      │   └── ia32/
      └── darwin/
          └── x64/
              └── app-1.1.0.dmg
```

**文件命名规则**：
- 格式：`app-{version}.{ext}`
- 示例：`app-1.1.0.exe`, `app-1.1.0.dmg`

**下载 URL 生成**：
- 基础 URL：`http://work.light120.com/downloads/`
- 完整 URL：`http://work.light120.com/downloads/app-1.1.0.exe`

## 关键逻辑说明

### 1. 版本号比较逻辑

**字符串比较规则**：
- 将版本号按 "." 分割成数组：["1", "1", "0"]
- 逐位比较数字大小
- 主版本号优先级最高，依次递减

**示例**：
```javascript
// 伪代码
compareVersion("1.1.0", "1.0.0") → true  // 1.1.0 > 1.0.0
compareVersion("2.0.0", "1.9.9") → true  // 2.0.0 > 1.9.9
compareVersion("1.0.0", "1.0.0") → false // 相等
```

### 2. 文件哈希计算

**计算方法**：
- 使用 SHA256 算法
- 读取文件内容，计算哈希值
- 返回小写的十六进制字符串

**用途**：
- 客户端下载后校验文件完整性
- 防止文件被篡改
- 确保文件下载完整

### 3. 强制更新逻辑

**force_update 字段**：
- `true`: 强制更新，客户端必须更新才能使用
- `false`: 可选更新，客户端可以选择稍后更新

**业务场景**：
- 安全漏洞修复 → 强制更新
- 重大功能更新 → 强制更新
- 小版本更新 → 可选更新

### 4. 平台和架构支持

**支持列表**：
- Windows: `win32` + `x64` / `ia32`
- macOS: `darwin` + `x64` / `arm64`
- Linux: `linux` + `x64` / `arm64`

**查询逻辑**：
- 必须同时匹配 platform 和 arch
- 如果某个组合没有版本，返回空结果

## 安全考虑

### 1. 文件下载安全

- **HTTPS 下载**：优先使用 HTTPS 协议
- **文件校验**：提供 SHA256 哈希值供客户端校验
- **文件大小验证**：返回文件大小，客户端可以验证下载完整性

### 2. 权限控制

- **序列号验证**：可以根据 sn_code 控制哪些设备可以更新
- **版本状态**：使用 status 字段控制版本是否可用
- **IP 限制**：可以限制下载 IP 范围（可选）

### 3. 防止恶意更新

- **文件类型验证**：只允许上传 .exe、.dmg、.AppImage 等安装包
- **文件大小限制**：设置最大文件大小限制
- **版本号验证**：验证版本号格式是否正确

## 返回状态码说明

| code | 说明 | 处理方式 |
|------|------|----------|
| 0 | 成功 | 检查 data 是否为空判断是否有更新 |
| 400 | 参数错误 | 客户端提示参数错误 |
| 401 | 未授权 | 客户端提示未授权 |
| 404 | 未找到版本 | 客户端提示版本不存在 |
| 500 | 服务器错误 | 客户端提示服务器错误，稍后重试 |

## 示例场景

### 场景1：有新版本

**请求**：
```
GET /version/check?current_version=1.0.0&platform=win32&arch=x64&sn_code=GHJU
```

**响应**：
```json
{
  "code": 0,
  "message": "success",
  "data": {
    "version": "1.1.0",
    "download_url": "http://work.light120.com/downloads/app-1.1.0.exe",
    "release_notes": "1. 修复了登录问题\n2. 新增自动升级功能",
    "force_update": false,
    "file_size": 52428800,
    "file_hash": "a1b2c3d4e5f6..."
  }
}
```

### 场景2：已是最新版本

**请求**：
```
GET /version/check?current_version=1.1.0&platform=win32&arch=x64&sn_code=GHJU
```

**响应**：
```json
{
  "code": 0,
  "message": "已是最新版本",
  "data": null
}
```

### 场景3：参数错误

**请求**：
```
GET /version/check?current_version=1.0.0
```

**响应**：
```json
{
  "code": 400,
  "message": "缺少必要参数：platform, arch",
  "data": null
}
```

## 注意事项

1. **日期字段命名**：统一使用 `create_time` 和 `last_modify_time`
2. **版本号格式**：严格按照 x.y.z 格式，便于版本比较
3. **文件存储**：建议使用 CDN 或静态文件服务器，提高下载速度
4. **日志记录**：记录版本检查请求，便于统计和分析
5. **缓存策略**：可以考虑缓存最新版本信息，减少数据库查询
6. **灰度发布**：可以通过 sn_code 控制部分设备先更新（可选）

## 实现优先级

1. **基础功能**：版本检查、版本比较、返回下载信息
2. **文件管理**：文件上传、文件存储、哈希计算
3. **安全功能**：文件校验、权限控制
4. **管理功能**：版本管理后台、历史记录

