新功能: - 创建AI聊天助手组件(AIChatWidget) - 支持文字+图片多模态对话 - 集成Gemini AI API - 支持图片编辑和内容生成 - 实时对话历史管理 - 优雅的UI设计,支持黑夜模式 技术实现: - 后端API代理Gemini API(/api/ai-chat) - 支持最多5张图片上传 - 流式响应处理 - 对话历史管理 - Base64图片处理 配置: - 在.env中添加Gemini API配置 - GEMINI_API_KEY - GEMINI_API_BASE_URL - GEMINI_MODEL 替换原弹幕功能,提供更强大的AI助手体验!
142 lines
4.9 KiB
JavaScript
Executable File
142 lines
4.9 KiB
JavaScript
Executable File
const fs = require('fs');
|
|
const path = require('path');
|
|
const logger = require('./logger');
|
|
|
|
/**
|
|
* 清理指定目录中超过指定时间的文件
|
|
* @param {string} directory 要清理的目录路径
|
|
* @param {number} maxAgeHours 文件最大保留时间(小时)
|
|
* @param {object} customLogger 自定义日志对象(可选)
|
|
* @param {boolean} isDryRun 是否为模拟运行模式,不实际删除文件
|
|
* @returns {Promise<{deletedFiles: number, sizeFreed: number}>} 删除的文件数量和释放的空间大小
|
|
*/
|
|
async function cleanupDirectory(directory, maxAgeHours = 24, customLogger = null, isDryRun = false) {
|
|
// 使用提供的日志器或默认日志器
|
|
const log = customLogger || logger;
|
|
|
|
try {
|
|
// 确保目录存在
|
|
if (!fs.existsSync(directory)) {
|
|
log.warn(`清理目录不存在: ${directory}`);
|
|
return { deletedFiles: 0, sizeFreed: 0 };
|
|
}
|
|
|
|
// 获取当前时间
|
|
const now = Date.now();
|
|
const maxAgeMs = maxAgeHours * 60 * 60 * 1000;
|
|
|
|
let deletedCount = 0;
|
|
let totalSize = 0;
|
|
|
|
// 读取目录内所有文件
|
|
const files = fs.readdirSync(directory);
|
|
log.info(`扫描目录 ${directory} 中的 ${files.length} 个文件`);
|
|
|
|
for (const file of files) {
|
|
const filePath = path.join(directory, file);
|
|
|
|
// 获取文件状态
|
|
const stats = fs.statSync(filePath);
|
|
|
|
// 跳过目录
|
|
if (stats.isDirectory()) {
|
|
continue;
|
|
}
|
|
|
|
// 计算文件年龄
|
|
const fileAge = now - stats.mtime.getTime();
|
|
|
|
// 如果文件超过最大年龄,删除它
|
|
if (fileAge > maxAgeMs) {
|
|
const fileSize = stats.size;
|
|
totalSize += fileSize;
|
|
|
|
const ageHours = (fileAge / 1000 / 60 / 60).toFixed(1);
|
|
const fileSizeMB = (fileSize / 1024 / 1024).toFixed(2);
|
|
|
|
if (isDryRun) {
|
|
// 模拟模式,只记录不删除
|
|
log.info(`将删除文件: ${filePath} (${fileSizeMB}MB, 年龄: ${ageHours}小时)`);
|
|
deletedCount++;
|
|
} else {
|
|
try {
|
|
fs.unlinkSync(filePath);
|
|
deletedCount++;
|
|
log.info(`已删除文件: ${filePath} (${fileSizeMB}MB, 年龄: ${ageHours}小时)`);
|
|
} catch (error) {
|
|
log.error(`删除文件失败: ${filePath}, 错误: ${error.message}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const actionText = isDryRun ? '将删除' : '删除了';
|
|
log.info(`清理${isDryRun ? '模拟' : ''}完成: ${actionText} ${deletedCount} 个文件, 总计${isDryRun ? '将' : ''}释放 ${(totalSize / 1024 / 1024).toFixed(2)}MB 空间`);
|
|
return { deletedFiles: deletedCount, sizeFreed: totalSize };
|
|
} catch (error) {
|
|
log.error(`清理目录时出错: ${directory}, 错误: ${error.message}`);
|
|
return { deletedFiles: 0, sizeFreed: 0 };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 执行所有目录的清理操作
|
|
* @param {object} customLogger 自定义日志对象(可选)
|
|
* @param {boolean} isDryRun 是否为模拟运行,不实际删除文件
|
|
* @returns {Promise<{totalFiles: number, totalSize: number}>} 清理结果
|
|
*/
|
|
async function runCleanup(customLogger = null, isDryRun = false) {
|
|
// 使用提供的日志器或默认日志器
|
|
const log = customLogger || logger;
|
|
|
|
log.info(`开始执行文件清理操作${isDryRun ? ' (模拟运行)' : ''}...`);
|
|
|
|
const baseDir = path.join(__dirname, '..');
|
|
let totalFiles = 0;
|
|
let totalSize = 0;
|
|
|
|
// 清理临时上传目录
|
|
const tempUploadsDir = path.join(baseDir, 'uploads/temp');
|
|
const tempResult = await cleanupDirectory(tempUploadsDir, 24, log, isDryRun); // 清理24小时前的文件
|
|
totalFiles += tempResult.deletedFiles;
|
|
totalSize += tempResult.sizeFreed;
|
|
|
|
// 清理处理后的文件目录
|
|
const processedDir = path.join(baseDir, 'uploads/processed');
|
|
const processedResult = await cleanupDirectory(processedDir, 72, log, isDryRun); // 清理72小时前的文件
|
|
totalFiles += processedResult.deletedFiles;
|
|
totalSize += processedResult.sizeFreed;
|
|
|
|
// 清理公共上传目录
|
|
const publicUploadsDir = path.join(baseDir, '../public/uploads');
|
|
const publicResult = await cleanupDirectory(publicUploadsDir, 168, log, isDryRun); // 清理7天前的文件
|
|
totalFiles += publicResult.deletedFiles;
|
|
totalSize += publicResult.sizeFreed;
|
|
|
|
const totalSizeMB = (totalSize / (1024 * 1024)).toFixed(2);
|
|
log.info(`文件清理操作完成,${isDryRun ? '将' : '已'}清理 ${totalFiles} 个文件,${isDryRun ? '将' : ''}释放 ${totalSizeMB} MB 空间`);
|
|
|
|
return {
|
|
totalFiles,
|
|
totalSize
|
|
};
|
|
}
|
|
|
|
// 导出函数供其他模块使用
|
|
module.exports = {
|
|
cleanupDirectory,
|
|
runCleanup
|
|
};
|
|
|
|
// 如果直接运行此脚本,执行清理
|
|
if (require.main === module) {
|
|
runCleanup()
|
|
.then(() => {
|
|
console.log('清理任务已完成');
|
|
process.exit(0);
|
|
})
|
|
.catch(error => {
|
|
console.error('清理任务失败:', error);
|
|
process.exit(1);
|
|
});
|
|
}
|