XNSim/XNSimPortal/routes/service-dev.js

335 lines
10 KiB
JavaScript
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.

const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const {
getServices,
getServiceVersionsByClassName,
saveServiceVersion,
createService
} = require('../utils/service-utils');
const {
serviceCodeGen,
serviceCodeZip,
serviceCodeUnzip,
serviceCodeCompile
} = require('../utils/xnCoreService');
// 获取所有服务列表
router.get('/services', (req, res) => {
try {
const services = getServices();
res.json(services);
} catch (error) {
console.error('获取服务列表失败:', error);
res.status(500).json({ error: '获取服务列表失败', details: error.message });
}
});
// 获取指定ClassName的服务版本
router.get('/service-versions/:className', (req, res) => {
try {
const className = req.params.className;
if (!className) {
return res.status(400).json({ error: '服务类名不能为空' });
}
const versions = getServiceVersionsByClassName(className);
// 确保版本列表每项都有Name属性如果没有则使用列名一致性处理
const processedVersions = versions.map(version => {
// 如果没有Name属性(可能是表结构原因),则使用与前端组件兼容的方式
if (version.Name === undefined && version.ServiceName) {
version.Name = version.ServiceName;
}
return version;
});
res.json(processedVersions);
} catch (error) {
console.error(`获取服务版本失败: ${error.message}`);
res.status(500).json({ error: '获取服务版本失败', details: error.message });
}
});
// 保存服务版本信息
router.post('/service-versions', (req, res) => {
try {
const versionData = req.body;
if (!versionData || !versionData.ClassName) {
return res.status(400).json({ error: '缺少必要的服务版本数据' });
}
// 确保数据字段一致性
if (versionData.ServiceName === undefined && versionData.Name) {
versionData.ServiceName = versionData.Name;
}
// 验证 CmdList 和 OtherParam 是否为有效的 JSON 字符串
if (versionData.CmdList !== undefined) {
try {
JSON.parse(versionData.CmdList);
} catch (e) {
return res.status(400).json({ error: 'CmdList 必须是有效的 JSON 字符串' });
}
}
if (versionData.OtherParam !== undefined) {
try {
JSON.parse(versionData.OtherParam);
} catch (e) {
return res.status(400).json({ error: 'OtherParam 必须是有效的 JSON 字符串' });
}
}
const result = saveServiceVersion(versionData);
res.json(result);
} catch (error) {
console.error(`保存服务版本失败: ${error.message}`);
res.status(500).json({ error: '保存服务版本失败', details: error.message });
}
});
// 创建新服务
router.post('/services', (req, res) => {
try {
const serviceData = req.body;
if (!serviceData || !serviceData.ClassName || !serviceData.ServiceName || !serviceData.ServiceName_CN) {
return res.status(400).json({ error: '缺少必要的服务数据' });
}
// 验证类名是否以XN开头
if (!serviceData.ClassName.startsWith('XN')) {
return res.status(400).json({ error: '服务类名必须以XN开头' });
}
const result = createService(serviceData);
res.json(result);
} catch (error) {
console.error(`创建服务失败: ${error.message}`);
res.status(500).json({ error: '创建服务失败', details: error.message });
}
});
// 生成服务代码
router.post('/generate-code', (req, res) => {
try {
const { className, version } = req.body;
if (!className || !version) {
return res.status(400).json({ error: '缺少必要的参数className 和 version' });
}
const result = serviceCodeGen(className, version);
if (result.includes('成功')) {
res.json({ success: true, message: result });
} else {
res.status(500).json({ success: false, error: result });
}
} catch (error) {
console.error(`生成服务代码失败: ${error.message}`);
res.status(500).json({ error: '生成服务代码失败', details: error.message });
}
});
// 压缩服务代码
router.post('/zip-code', (req, res) => {
try {
const { className, version } = req.body;
if (!className || !version) {
return res.status(400).json({ error: '缺少必要的参数className 和 version' });
}
const result = serviceCodeZip(className, version);
if (result.success) {
res.json({
success: true,
message: result.message,
dstPath: result.dstPath
});
} else {
res.status(500).json({ success: false, error: result.message });
}
} catch (error) {
console.error(`压缩服务代码失败: ${error.message}`);
res.status(500).json({ error: '压缩服务代码失败', details: error.message });
}
});
// 解压服务代码
router.post('/unzip-code', (req, res) => {
try {
const { className, version, srcPath } = req.body;
if (!className || !version || !srcPath) {
return res.status(400).json({ error: '缺少必要的参数className、version 和 srcPath' });
}
const result = serviceCodeUnzip(className, version, srcPath);
if (result.includes('成功')) {
res.json({ success: true, message: result });
} else {
res.status(500).json({ success: false, error: result });
}
} catch (error) {
console.error(`解压服务代码失败: ${error.message}`);
res.status(500).json({ error: '解压服务代码失败', details: error.message });
}
});
// 编译服务代码
router.post('/compile-code', (req, res) => {
try {
const { className, version } = req.body;
if (!className || !version) {
return res.status(400).json({ error: '缺少必要的参数className 和 version' });
}
const result = serviceCodeCompile(className, version);
if (result.includes('成功')) {
res.json({ success: true, message: result });
} else {
res.status(500).json({ success: false, error: result });
}
} catch (error) {
console.error(`编译服务代码失败: ${error.message}`);
res.status(500).json({ error: '编译服务代码失败', details: error.message });
}
});
// 下载ZIP文件
router.post('/download-zip', (req, res) => {
try {
const { filePath } = req.body;
if (!filePath) {
return res.status(400).json({ error: '缺少文件路径参数' });
}
// 检查文件是否存在
if (!fs.existsSync(filePath)) {
return res.status(404).json({ error: '文件不存在' });
}
// 检查文件是否为ZIP格式
if (!filePath.toLowerCase().endsWith('.zip')) {
return res.status(400).json({ error: '只能下载ZIP格式的文件' });
}
// 获取文件名
const fileName = path.basename(filePath);
// 设置响应头
res.setHeader('Content-Type', 'application/zip');
res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
// 发送文件
res.sendFile(filePath);
} catch (error) {
console.error(`下载ZIP文件失败: ${error.message}`);
res.status(500).json({ error: '下载ZIP文件失败', details: error.message });
}
});
// 配置multer用于文件上传
const storage = multer.diskStorage({
destination: function (req, file, cb) {
// 获取XNCore环境变量
const xnCorePath = process.env.XNCore || '';
if (!xnCorePath) {
return cb(new Error('XNCore环境变量未设置'));
}
// 创建ServiceProjects目录
const serviceProjectsDir = path.join(xnCorePath, 'ServiceProjects');
if (!fs.existsSync(serviceProjectsDir)) {
fs.mkdirSync(serviceProjectsDir, { recursive: true });
}
cb(null, serviceProjectsDir);
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
});
const upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
// 只允许ZIP文件
if (file.mimetype === 'application/zip' || file.originalname.toLowerCase().endsWith('.zip')) {
cb(null, true);
} else {
cb(new Error('只允许上传ZIP格式的文件'), false);
}
},
limits: {
fileSize: 100 * 1024 * 1024 // 限制100MB
}
});
// 上传ZIP文件
router.post('/upload-zip', upload.single('file'), (req, res) => {
try {
// 检查XNCore环境变量
const xnCorePath = process.env.XNCore || '';
if (!xnCorePath) {
return res.status(500).json({ error: 'XNCore环境变量未设置' });
}
if (!req.file) {
return res.status(400).json({ error: '没有选择文件' });
}
const filePath = req.file.path;
const fileName = req.file.filename;
// 验证文件是否成功保存到ServiceProjects目录
if (!fs.existsSync(filePath)) {
return res.status(500).json({ error: '文件上传失败,文件未保存到目标目录' });
}
res.json({
success: true,
message: '文件上传成功',
filePath: filePath,
fileName: fileName,
originalName: req.file.originalname,
uploadDir: path.dirname(filePath)
});
} catch (error) {
console.error(`上传ZIP文件失败: ${error.message}`);
res.status(500).json({ error: '上传ZIP文件失败', details: error.message });
}
});
// 处理multer错误
router.use('/upload-zip', (error, req, res, next) => {
if (error instanceof multer.MulterError) {
if (error.code === 'LIMIT_FILE_SIZE') {
return res.status(400).json({ error: '文件大小超过限制最大100MB' });
}
return res.status(400).json({ error: `文件上传错误: ${error.message}` });
}
if (error.message === 'XNCore环境变量未设置') {
return res.status(500).json({ error: 'XNCore环境变量未设置无法上传文件' });
}
if (error.message.includes('只允许上传ZIP格式的文件')) {
return res.status(400).json({ error: '只允许上传ZIP格式的文件' });
}
console.error('文件上传错误:', error);
res.status(500).json({ error: '文件上传失败', details: error.message });
});
module.exports = router;