/** * 版本管理API - 后台管理 * 提供版本信息的CRUD操作和版本控制功能 */ const Framework = require("../../framework/node-core-framework.js"); const version_service = require('../services/version_service.js'); const config = require('../../config/config.js'); module.exports = { /** * @swagger * /admin_api/version/list: * post: * summary: 获取版本列表 * description: 分页获取所有版本信息 * tags: [后台-版本管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * seachOption: * type: object * description: 搜索条件 * properties: * key: * type: string * description: 搜索字段(version/platform/arch) * value: * type: string * description: 搜索值 * platform: * type: string * description: 平台筛选(win32/darwin/linux) * arch: * type: string * description: 架构筛选(x64/ia32/arm64) * status: * type: integer * description: 状态筛选(1:启用 0:禁用) * pageOption: * type: object * description: 分页选项 * properties: * page: * type: integer * description: 页码 * pageSize: * type: integer * description: 每页数量 * responses: * 200: * description: 获取成功 */ 'POST /version/list': async (ctx) => { const models = Framework.getModels(); const { version_info } = models; const { op } = models; const body = ctx.getBody(); const seachOption = body.seachOption || {}; const pageOption = body.pageOption || {}; // 获取分页参数 const page = pageOption.page || 1; const pageSize = pageOption.pageSize || 20; const limit = pageSize; const offset = (page - 1) * pageSize; const where = {}; // 平台筛选 if (seachOption.platform) { where.platform = seachOption.platform; } // 架构筛选 if (seachOption.arch) { where.arch = seachOption.arch; } // 状态筛选 if (seachOption.status !== undefined && seachOption.status !== null) { where.status = seachOption.status; } // 搜索:版本号、平台、架构 if (seachOption.key && seachOption.value) { const key = seachOption.key; const value = seachOption.value; if (key === 'version') { where.version = { [op.like]: `%${value}%` }; } else if (key === 'platform') { where.platform = { [op.like]: `%${value}%` }; } else if (key === 'arch') { where.arch = { [op.like]: `%${value}%` }; } } const result = await version_info.findAndCountAll({ where, limit, offset, order: [['create_time', 'DESC']] }); return ctx.success({ rows: result.rows, count: result.count }); }, /** * @swagger * /admin_api/version/detail: * post: * summary: 获取版本详情 * description: 根据版本ID获取详细信息 * tags: [后台-版本管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - id * properties: * id: * type: integer * description: 版本ID * responses: * 200: * description: 获取成功 */ 'POST /version/detail': async (ctx) => { const models = Framework.getModels(); const { version_info } = models; const { id } = ctx.getBody(); if (!id) { return ctx.fail('版本ID不能为空'); } const version = await version_info.findByPk(id); if (!version) { return ctx.fail('版本不存在'); } return ctx.success(version); }, /** * @swagger * /admin_api/version/create: * post: * summary: 创建版本 * description: 创建新版本信息 * tags: [后台-版本管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - version * - platform * - arch * - download_url * - file_path * properties: * version: * type: string * description: 版本号(x.y.z 格式) * platform: * type: string * description: 平台类型 * arch: * type: string * description: 架构类型 * download_url: * type: string * description: 下载地址 * file_path: * type: string * description: 服务器文件路径 * file_size: * type: integer * description: 文件大小(字节) * file_hash: * type: string * description: SHA256 哈希值 * release_notes: * type: string * description: 更新日志 * force_update: * type: integer * description: 是否强制更新(1:是 0:否) * status: * type: integer * description: 状态(1:启用 0:禁用) * responses: * 200: * description: 创建成功 */ 'POST /version/create': async (ctx) => { const models = Framework.getModels(); const { version_info } = models; const body = ctx.getBody(); // 参数验证 if (!body.version) { return ctx.fail('版本号不能为空'); } if (!body.platform) { return ctx.fail('平台类型不能为空'); } if (!body.arch) { return ctx.fail('架构类型不能为空'); } if (!body.download_url) { return ctx.fail('下载地址不能为空'); } if (!body.file_path) { return ctx.fail('文件路径不能为空'); } // 验证版本号格式 if (!version_service.is_valid_version(body.version)) { return ctx.fail('版本号格式错误,应为 x.y.z 格式'); } // 验证平台类型 if (!version_service.is_valid_platform(body.platform)) { return ctx.fail('平台类型错误,应为 win32/darwin/linux'); } // 验证架构类型 if (!version_service.is_valid_arch(body.arch)) { return ctx.fail('架构类型错误,应为 x64/ia32/arm64'); } // 检查版本是否已存在 const existing = await version_info.findOne({ where: { version: body.version, platform: body.platform, arch: body.arch } }); if (existing) { return ctx.fail('该版本已存在'); } // 如果提供了文件路径,计算文件大小和哈希 if (body.file_path) { try { const fs = require('fs'); const path = require('path'); 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, '版本创建成功'); }, /** * @swagger * /admin_api/version/update: * post: * summary: 更新版本 * description: 更新版本信息 * tags: [后台-版本管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - id * properties: * id: * type: integer * description: 版本ID * version: * type: string * description: 版本号 * platform: * type: string * description: 平台类型 * arch: * type: string * description: 架构类型 * download_url: * type: string * description: 下载地址 * file_path: * type: string * description: 文件路径 * release_notes: * type: string * description: 更新日志 * force_update: * type: integer * description: 是否强制更新 * status: * type: integer * description: 状态 * responses: * 200: * description: 更新成功 */ 'POST /version/update': async (ctx) => { const models = Framework.getModels(); const { version_info } = models; const { op } = models; const body = ctx.getBody(); if (!body.id) { return ctx.fail('版本ID不能为空'); } const version = await version_info.findByPk(body.id); if (!version) { return ctx.fail('版本不存在'); } // 如果更新了版本号、平台或架构,检查是否重复 if (body.version || body.platform || body.arch) { const check_version = body.version || version.version; const check_platform = body.platform || version.platform; const check_arch = body.arch || version.arch; const existing = await version_info.findOne({ where: { version: check_version, platform: check_platform, arch: check_arch, id: { [op.ne]: body.id } } }); if (existing) { return ctx.fail('该版本已存在'); } } // 如果更新了文件路径,重新计算文件大小和哈希 if (body.file_path && body.file_path !== version.file_path) { try { const fs = require('fs'); const path = require('path'); const full_path = path.resolve(body.file_path); if (fs.existsSync(full_path)) { const stats = fs.statSync(full_path); body.file_size = stats.size; body.file_hash = await version_service.calculate_file_hash(full_path); } } catch (error) { console.error('计算文件信息失败:', error); } } // 更新版本 await version_info.update({ version: body.version, platform: body.platform, arch: body.arch, download_url: body.download_url, file_path: body.file_path, file_size: body.file_size, file_hash: body.file_hash, release_notes: body.release_notes, force_update: body.force_update, status: body.status }, { where: { id: body.id } }); return ctx.success(null, '版本更新成功'); }, /** * @swagger * /admin_api/version/delete: * post: * summary: 删除版本 * description: 删除指定的版本信息 * tags: [后台-版本管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - id * properties: * id: * type: integer * description: 版本ID * responses: * 200: * description: 删除成功 */ 'POST /version/delete': async (ctx) => { const models = Framework.getModels(); const { version_info } = models; const { id } = ctx.getBody(); if (!id) { return ctx.fail('版本ID不能为空'); } const result = await version_info.destroy({ where: { id } }); if (result === 0) { return ctx.fail('版本不存在'); } return ctx.success(null, '版本删除成功'); }, /** * @swagger * /admin_api/version/update_status: * post: * summary: 更新版本状态 * description: 启用或禁用版本 * tags: [后台-版本管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - id * - status * properties: * id: * type: integer * description: 版本ID * status: * type: integer * description: 状态(1:启用 0:禁用) * responses: * 200: * description: 更新成功 */ 'POST /version/update_status': async (ctx) => { const models = Framework.getModels(); const { version_info } = models; const { id, status } = ctx.getBody(); if (!id) { return ctx.fail('版本ID不能为空'); } if (status === undefined || status === null) { return ctx.fail('状态不能为空'); } const result = await version_info.update({ status: status }, { where: { id } }); if (result[0] === 0) { return ctx.fail('版本不存在'); } return ctx.success(null, '状态更新成功'); } };