feat: Initial commit of PDF Tools project
This commit is contained in:
279
server/routes/system.js
Normal file
279
server/routes/system.js
Normal file
@@ -0,0 +1,279 @@
|
||||
const express = require('express');
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// 系统健康检查
|
||||
router.get('/health', (req, res) => {
|
||||
try {
|
||||
const uptime = process.uptime();
|
||||
const memoryUsage = process.memoryUsage();
|
||||
const cpuUsage = process.cpuUsage();
|
||||
|
||||
const healthData = {
|
||||
status: 'OK',
|
||||
timestamp: new Date().toISOString(),
|
||||
uptime: {
|
||||
seconds: Math.floor(uptime),
|
||||
readable: formatUptime(uptime)
|
||||
},
|
||||
memory: {
|
||||
rss: formatBytes(memoryUsage.rss),
|
||||
heapTotal: formatBytes(memoryUsage.heapTotal),
|
||||
heapUsed: formatBytes(memoryUsage.heapUsed),
|
||||
external: formatBytes(memoryUsage.external)
|
||||
},
|
||||
cpu: {
|
||||
user: cpuUsage.user,
|
||||
system: cpuUsage.system
|
||||
},
|
||||
system: {
|
||||
platform: os.platform(),
|
||||
arch: os.arch(),
|
||||
nodeVersion: process.version,
|
||||
totalMemory: formatBytes(os.totalmem()),
|
||||
freeMemory: formatBytes(os.freemem()),
|
||||
loadAverage: os.loadavg(),
|
||||
cpuCount: os.cpus().length
|
||||
}
|
||||
};
|
||||
|
||||
res.json(healthData);
|
||||
|
||||
} catch (error) {
|
||||
console.error('健康检查错误:', error);
|
||||
res.status(500).json({
|
||||
status: 'ERROR',
|
||||
message: '系统健康检查失败',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 系统统计信息
|
||||
router.get('/stats', (req, res) => {
|
||||
try {
|
||||
const uploadDir = path.join(__dirname, '../uploads');
|
||||
let filesCount = 0;
|
||||
let totalSize = 0;
|
||||
|
||||
if (fs.existsSync(uploadDir)) {
|
||||
const files = fs.readdirSync(uploadDir);
|
||||
filesCount = files.length;
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(uploadDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
totalSize += stats.size;
|
||||
});
|
||||
}
|
||||
|
||||
const statsData = {
|
||||
files: {
|
||||
count: filesCount,
|
||||
totalSize: formatBytes(totalSize)
|
||||
},
|
||||
conversions: {
|
||||
total: 0, // 这里应该从数据库查询
|
||||
successful: 0,
|
||||
failed: 0,
|
||||
inProgress: 0
|
||||
},
|
||||
users: {
|
||||
total: 0, // 这里应该从数据库查询
|
||||
active: 0,
|
||||
newToday: 0
|
||||
},
|
||||
performance: {
|
||||
averageConversionTime: '0s',
|
||||
queueLength: 0,
|
||||
errorRate: '0%'
|
||||
}
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: statsData,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取系统统计错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取系统统计失败'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 支持的格式信息
|
||||
router.get('/formats', (req, res) => {
|
||||
try {
|
||||
const supportedFormats = {
|
||||
input: [
|
||||
{
|
||||
format: 'pdf',
|
||||
mimeType: 'application/pdf',
|
||||
description: 'PDF文档',
|
||||
maxSize: '50MB'
|
||||
}
|
||||
],
|
||||
output: [
|
||||
{
|
||||
format: 'docx',
|
||||
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
description: 'Microsoft Word文档',
|
||||
features: ['保持布局', '提取图片', 'OCR支持']
|
||||
},
|
||||
{
|
||||
format: 'html',
|
||||
mimeType: 'text/html',
|
||||
description: 'HTML网页',
|
||||
features: ['响应式设计', '嵌入图片', 'CSS框架']
|
||||
},
|
||||
{
|
||||
format: 'txt',
|
||||
mimeType: 'text/plain',
|
||||
description: '纯文本',
|
||||
features: ['提取文本', '保留换行', '字符编码']
|
||||
},
|
||||
{
|
||||
format: 'png',
|
||||
mimeType: 'image/png',
|
||||
description: 'PNG图片',
|
||||
features: ['高质量', '透明背景', '无损压缩']
|
||||
},
|
||||
{
|
||||
format: 'jpg',
|
||||
mimeType: 'image/jpeg',
|
||||
description: 'JPEG图片',
|
||||
features: ['压缩率高', '质量可调', '广泛支持']
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: supportedFormats
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取格式信息错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取格式信息失败'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 系统配置信息
|
||||
router.get('/config', (req, res) => {
|
||||
try {
|
||||
const config = {
|
||||
upload: {
|
||||
maxFileSize: '50MB',
|
||||
allowedTypes: ['application/pdf'],
|
||||
uploadDir: process.env.UPLOAD_DIR || './uploads'
|
||||
},
|
||||
conversion: {
|
||||
timeout: process.env.CONVERSION_TIMEOUT || 300000,
|
||||
maxConcurrent: process.env.MAX_CONCURRENT_CONVERSIONS || 5,
|
||||
queueLimit: 100
|
||||
},
|
||||
security: {
|
||||
rateLimiting: process.env.ENABLE_RATE_LIMITING === 'true',
|
||||
rateLimit: {
|
||||
window: process.env.RATE_LIMIT_WINDOW || 900000,
|
||||
max: process.env.RATE_LIMIT_MAX || 100
|
||||
}
|
||||
},
|
||||
features: {
|
||||
userRegistration: true,
|
||||
batchConversion: true,
|
||||
previewSupport: false,
|
||||
cloudStorage: false
|
||||
}
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: config
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取系统配置错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取系统配置失败'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 清理临时文件
|
||||
router.post('/cleanup', (req, res) => {
|
||||
try {
|
||||
const uploadDir = path.join(__dirname, '../uploads');
|
||||
const maxAge = 24 * 60 * 60 * 1000; // 24小时
|
||||
const now = Date.now();
|
||||
let cleanedCount = 0;
|
||||
let cleanedSize = 0;
|
||||
|
||||
if (fs.existsSync(uploadDir)) {
|
||||
const files = fs.readdirSync(uploadDir);
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(uploadDir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
|
||||
if (now - stats.mtime.getTime() > maxAge) {
|
||||
cleanedSize += stats.size;
|
||||
fs.unlinkSync(filePath);
|
||||
cleanedCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: '临时文件清理完成',
|
||||
data: {
|
||||
cleanedFiles: cleanedCount,
|
||||
freedSpace: formatBytes(cleanedSize)
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('清理临时文件错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '清理临时文件失败'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 辅助函数:格式化字节大小
|
||||
function formatBytes(bytes, decimals = 2) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
// 辅助函数:格式化运行时间
|
||||
function formatUptime(uptime) {
|
||||
const days = Math.floor(uptime / 86400);
|
||||
const hours = Math.floor((uptime % 86400) / 3600);
|
||||
const minutes = Math.floor((uptime % 3600) / 60);
|
||||
const seconds = Math.floor(uptime % 60);
|
||||
|
||||
return `${days}d ${hours}h ${minutes}m ${seconds}s`;
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user