355 lines
11 KiB
JavaScript
355 lines
11 KiB
JavaScript
const Framework = require("../../framework/node-core-framework.js");
|
||
const version_service = require('../services/version_service.js');
|
||
const config = require('../../config/config.js');
|
||
const ossToolService = require('../services/oss_tool_service.js');
|
||
const crypto = require('crypto');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
/**
|
||
* 版本管理控制器
|
||
* 提供版本检查、版本管理等功能
|
||
*/
|
||
module.exports = {
|
||
/**
|
||
* @swagger
|
||
* /api/version/check:
|
||
* get:
|
||
* summary: 检查是否有新版本
|
||
* description: 根据当前版本号、平台和架构检查是否有可用更新
|
||
* tags: [前端-版本管理]
|
||
* parameters:
|
||
* - in: query
|
||
* name: current_version
|
||
* required: true
|
||
* schema:
|
||
* type: string
|
||
* pattern: '^\d+\.\d+\.\d+$'
|
||
* description: 当前版本号(x.y.z 格式,如 1.0.0)
|
||
* example: '1.0.0'
|
||
* - in: query
|
||
* name: platform
|
||
* required: true
|
||
* schema:
|
||
* type: string
|
||
* enum: [win32, darwin, linux]
|
||
* description: 平台类型
|
||
* example: 'win32'
|
||
* - in: query
|
||
* name: arch
|
||
* required: true
|
||
* schema:
|
||
* type: string
|
||
* enum: [x64, ia32, arm64]
|
||
* description: 架构类型
|
||
* example: 'x64'
|
||
* - in: query
|
||
* name: sn_code
|
||
* required: false
|
||
* schema:
|
||
* type: string
|
||
* description: 设备序列号(可选,用于权限控制)
|
||
* example: 'GHJU'
|
||
* responses:
|
||
* 200:
|
||
* description: 检查成功
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* properties:
|
||
* code:
|
||
* type: integer
|
||
* description: 状态码,0表示成功
|
||
* example: 0
|
||
* message:
|
||
* type: string
|
||
* description: 响应消息
|
||
* example: 'success'
|
||
* data:
|
||
* type: object
|
||
* nullable: true
|
||
* description: 版本信息,null表示已是最新版本
|
||
* properties:
|
||
* version:
|
||
* type: string
|
||
* description: 最新版本号
|
||
* example: '1.1.0'
|
||
* download_url:
|
||
* type: string
|
||
* description: 下载地址
|
||
* example: 'http://work.light120.com/downloads/app-1.1.0.exe'
|
||
* release_notes:
|
||
* type: string
|
||
* description: 更新日志
|
||
* example: '修复了一些bug,新增了xxx功能'
|
||
* force_update:
|
||
* type: boolean
|
||
* description: 是否强制更新
|
||
* example: false
|
||
* file_size:
|
||
* type: integer
|
||
* description: 文件大小(字节)
|
||
* example: 52428800
|
||
* file_hash:
|
||
* type: string
|
||
* description: SHA256 哈希值
|
||
* example: 'abc123def456...'
|
||
* 400:
|
||
* description: 参数错误
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* properties:
|
||
* code:
|
||
* type: integer
|
||
* example: 400
|
||
* message:
|
||
* type: string
|
||
* example: '缺少必要参数:current_version'
|
||
* 500:
|
||
* description: 服务器错误
|
||
*/
|
||
'GET /version/check': async (ctx) => {
|
||
try {
|
||
// 获取请求参数
|
||
const query = ctx.query || {};
|
||
const current_version = query.current_version;
|
||
const platform = query.platform;
|
||
const arch = query.arch;
|
||
const sn_code = query.sn_code; // 可选,用于权限控制
|
||
|
||
// 参数验证
|
||
if (!current_version) {
|
||
return ctx.fail('缺少必要参数:current_version', 400);
|
||
}
|
||
if (!platform) {
|
||
return ctx.fail('缺少必要参数:platform', 400);
|
||
}
|
||
if (!arch) {
|
||
return ctx.fail('缺少必要参数:arch', 400);
|
||
}
|
||
|
||
// 验证版本号格式
|
||
if (!version_service.is_valid_version(current_version)) {
|
||
return ctx.fail('版本号格式错误,应为 x.y.z 格式', 400);
|
||
}
|
||
|
||
// 验证平台类型
|
||
if (!version_service.is_valid_platform(platform)) {
|
||
return ctx.fail('平台类型错误,应为 win32/darwin/linux', 400);
|
||
}
|
||
|
||
// 验证架构类型
|
||
if (!version_service.is_valid_arch(arch)) {
|
||
return ctx.fail('架构类型错误,应为 x64/ia32/arm64', 400);
|
||
}
|
||
|
||
// 获取模型
|
||
const { version_info } = Framework.getModels();
|
||
|
||
// 查询所有启用状态的版本(按 platform + arch + status=1)
|
||
const all_versions = await version_info.findAll({
|
||
where: {
|
||
platform: platform,
|
||
arch: arch,
|
||
status: 1
|
||
}
|
||
});
|
||
|
||
// 如果没有找到版本信息
|
||
if (!all_versions || all_versions.length === 0) {
|
||
return ctx.success(null, '未找到该平台的版本信息');
|
||
}
|
||
|
||
// 按版本号排序(降序)
|
||
all_versions.sort((a, b) => {
|
||
return version_service.compare_version(b.version, a.version);
|
||
});
|
||
|
||
const latest = all_versions[0];
|
||
if (!latest) {
|
||
return ctx.success(null, '已是最新版本');
|
||
}
|
||
|
||
// 比较版本
|
||
const has_update = version_service.has_new_version(current_version, latest.version);
|
||
|
||
// 如果没有更新
|
||
if (!has_update) {
|
||
return ctx.success(null, '已是最新版本');
|
||
}
|
||
|
||
// 构建返回数据
|
||
const result = {
|
||
version: latest.version,
|
||
download_url: latest.download_url,
|
||
release_notes: latest.release_notes || '',
|
||
force_update: latest.force_update === 1,
|
||
file_size: latest.file_size || 0,
|
||
file_hash: latest.file_hash || ''
|
||
};
|
||
|
||
return ctx.success(result, 'success');
|
||
|
||
} catch (error) {
|
||
console.error('版本检查错误:', error);
|
||
return ctx.fail('服务器错误', 500);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @swagger
|
||
* /api/version/create:
|
||
* post:
|
||
* summary: 创建版本记录
|
||
* description: 创建新版本信息,用于发布脚本自动创建版本
|
||
* tags: [前端-版本管理]
|
||
* requestBody:
|
||
* required: true
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* required:
|
||
* - version
|
||
* - platform
|
||
* - arch
|
||
* properties:
|
||
* version:
|
||
* type: string
|
||
* description: 版本号(x.y.z 格式)
|
||
* example: '1.0.0'
|
||
* platform:
|
||
* type: string
|
||
* enum: [win32, darwin, linux]
|
||
* description: 平台类型
|
||
* example: 'win32'
|
||
* arch:
|
||
* type: string
|
||
* enum: [x64, ia32, arm64]
|
||
* description: 架构类型
|
||
* example: 'x64'
|
||
* download_url:
|
||
* type: string
|
||
* description: 下载地址(上传后更新)
|
||
* example: ''
|
||
* file_path:
|
||
* type: string
|
||
* description: 服务器文件路径
|
||
* example: '/path/to/file.exe'
|
||
* file_size:
|
||
* type: integer
|
||
* description: 文件大小(字节)
|
||
* example: 12345678
|
||
* file_hash:
|
||
* type: string
|
||
* description: SHA256 哈希值
|
||
* example: 'sha256-hash-value'
|
||
* release_notes:
|
||
* type: string
|
||
* description: 更新日志
|
||
* example: '修复了若干bug,优化了性能'
|
||
* force_update:
|
||
* type: integer
|
||
* description: 是否强制更新(1:是 0:否)
|
||
* example: 0
|
||
* status:
|
||
* type: integer
|
||
* description: 状态(1:启用 0:禁用)
|
||
* example: 1
|
||
* responses:
|
||
* 200:
|
||
* description: 创建成功
|
||
* 400:
|
||
* description: 参数错误
|
||
*/
|
||
'POST /version/create': async (ctx) => {
|
||
|
||
const models = Framework.getModels();
|
||
const { version_info } = models;
|
||
const body = ctx.getBody();
|
||
|
||
// 参数验证
|
||
if (!body.version) {
|
||
return ctx.fail('版本号不能为空', 400);
|
||
}
|
||
if (!body.platform) {
|
||
return ctx.fail('平台类型不能为空', 400);
|
||
}
|
||
if (!body.arch) {
|
||
return ctx.fail('架构类型不能为空', 400);
|
||
}
|
||
|
||
// 验证版本号格式
|
||
if (!version_service.is_valid_version(body.version)) {
|
||
return ctx.fail('版本号格式错误,应为 x.y.z 格式', 400);
|
||
}
|
||
|
||
// 验证平台类型
|
||
if (!version_service.is_valid_platform(body.platform)) {
|
||
return ctx.fail('平台类型错误,应为 win32/darwin/linux', 400);
|
||
}
|
||
|
||
// 验证架构类型
|
||
if (!version_service.is_valid_arch(body.arch)) {
|
||
return ctx.fail('架构类型错误,应为 x64/ia32/arm64', 400);
|
||
}
|
||
|
||
// 检查版本是否已存在
|
||
const existing = await version_info.findOne({
|
||
where: {
|
||
version: body.version,
|
||
platform: body.platform,
|
||
arch: body.arch
|
||
}
|
||
});
|
||
|
||
if (existing) {
|
||
return ctx.fail('该版本已存在', 400);
|
||
}
|
||
|
||
// 如果提供了文件路径,计算文件大小和哈希
|
||
if (body.file_path) {
|
||
try {
|
||
const full_path = path.resolve(body.file_path);
|
||
|
||
if (fs.existsSync(full_path)) {
|
||
// 计算文件大小
|
||
if (!body.file_size) {
|
||
const stats = fs.statSync(full_path);
|
||
body.file_size = stats.size;
|
||
}
|
||
|
||
// 计算文件哈希
|
||
if (!body.file_hash) {
|
||
body.file_hash = await version_service.calculate_file_hash(full_path);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('计算文件信息失败:', error);
|
||
}
|
||
}
|
||
|
||
// 创建版本
|
||
const version = await version_info.create({
|
||
version: body.version,
|
||
platform: body.platform,
|
||
arch: body.arch,
|
||
download_url: body.download_url || '',
|
||
file_path: body.file_path || '',
|
||
file_size: body.file_size || 0,
|
||
file_hash: body.file_hash || '',
|
||
release_notes: body.release_notes || '',
|
||
force_update: body.force_update || 0,
|
||
status: body.status !== undefined ? body.status : 1
|
||
});
|
||
|
||
return ctx.success(version, '版本创建成功');
|
||
|
||
},
|
||
|
||
};
|
||
|