diff --git a/README.md b/README.md index 4a08184..63f9552 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Pixiv 下载浏览管理器是一个基于 Web 的应用程序,提供以下功 ![作品id搜索](./pic/作品id搜索.png) ### 列表轮换 -- **通过作者搜索进入作品可以上下一个切换** +- **通过作者搜索进入作品可以上下一个切换,注意只有当页的30个,到末尾需要翻页再进入** - ![列表轮换](./pic/列表轮换.png) ### 下载管理 diff --git a/backend/server.js b/backend/server.js index 161b140..05dd891 100644 --- a/backend/server.js +++ b/backend/server.js @@ -19,6 +19,88 @@ const { authMiddleware } = require('./middleware/auth'); const PixivBackend = require('./core'); const proxyConfig = require('./config'); +// 自定义日志中间件 +function customLogger(req, res, next) { + // 过滤掉静态资源请求 + const isStaticResource = req.path.startsWith('/assets/') || + req.path.startsWith('/downloads/') || + req.path.includes('.js') || + req.path.includes('.css') || + req.path.includes('.ico') || + req.path.includes('.png') || + req.path.includes('.jpg') || + req.path.includes('.jpeg') || + req.path.includes('.gif') || + req.path.includes('.svg') || + req.path.includes('.woff') || + req.path.includes('.woff2') || + req.path.includes('.ttf') || + req.path.includes('.eot'); + + // 只记录API请求和重要请求 + if (!isStaticResource) { + const start = Date.now(); + + // 原始响应结束方法 + const originalEnd = res.end; + + // 重写响应结束方法以获取响应时间 + res.end = function(chunk, encoding) { + const duration = Date.now() - start; + const statusCode = res.statusCode; + const method = req.method; + const url = req.originalUrl; + + // 根据状态码选择颜色和图标 + let statusIcon, statusColor; + if (statusCode >= 200 && statusCode < 300) { + statusIcon = '✅'; + statusColor = '\x1b[32m'; // 绿色 + } else if (statusCode >= 300 && statusCode < 400) { + statusIcon = '🔄'; + statusColor = '\x1b[33m'; // 黄色 + } else if (statusCode >= 400 && statusCode < 500) { + statusIcon = '⚠️'; + statusColor = '\x1b[33m'; // 黄色 + } else { + statusIcon = '❌'; + statusColor = '\x1b[31m'; // 红色 + } + + // 根据请求类型选择图标 + let methodIcon; + switch (method) { + case 'GET': methodIcon = '📥'; break; + case 'POST': methodIcon = '📤'; break; + case 'PUT': methodIcon = '🔄'; break; + case 'DELETE': methodIcon = '🗑️'; break; + case 'PATCH': methodIcon = '🔧'; break; + default: methodIcon = '❓'; + } + + // 格式化时间 + const now = new Date(); + const timeStr = now.toLocaleTimeString('zh-CN', { + hour12: false, + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + + // 构建日志消息 + const logMessage = `${statusColor}${statusIcon} ${methodIcon} ${method} ${url} ${statusCode} ${duration}ms\x1b[0m`; + + // 输出日志 + console.log(`[${timeStr}] ${logMessage}`); + + // 调用原始的end方法 + originalEnd.call(this, chunk, encoding); + }; + } + + next(); +} + class PixivServer { constructor() { this.app = express(); @@ -30,7 +112,7 @@ class PixivServer { * 初始化服务器 */ async init() { - console.log('正在初始化 Pixiv 后端服务器...'); + console.log('\x1b[34m🔧 正在初始化 Pixiv 后端服务器...\x1b[0m'); // 设置代理 proxyConfig.setEnvironmentVariables(); @@ -48,15 +130,15 @@ class PixivServer { // 配置错误处理 - 临时注释掉 this.setupErrorHandling(); - console.log('服务器初始化完成'); + console.log('\x1b[32m✅ 服务器初始化完成\x1b[0m'); } /** * 配置中间件 */ setupMiddleware() { - // 日志中间件 - this.app.use(morgan('combined')); + // 自定义日志中间件(替换morgan) + this.app.use(customLogger); // CORS 中间件 this.app.use(cors({ @@ -132,14 +214,14 @@ class PixivServer { */ start() { this.app.listen(this.port, () => { - console.log(`🚀 Pixiv 后端服务器已启动`); - console.log(`📍 后端API: http://localhost:${this.port}`); - console.log(`🌐 前端页面: http://localhost:${this.port}`); - console.log(`🔗 健康检查: http://localhost:${this.port}/health`); - console.log(`📊 登录状态: ${this.backend.isLoggedIn ? '已登录' : '未登录'}`); + console.log('\x1b[32m✅ Pixiv 后端服务器已启动\x1b[0m'); + console.log(`\x1b[36m📍 服务地址: http://localhost:${this.port}\x1b[0m`); + console.log(`\x1b[36m🔗 健康检查: http://localhost:${this.port}/health\x1b[0m`); + console.log(`\x1b[33m📊 登录状态: ${this.backend.isLoggedIn ? '已登录' : '未登录'}\x1b[0m`); if (this.backend.isLoggedIn) { - console.log(`👤 用户: ${this.backend.config.user?.account}`); + console.log(`\x1b[33m👤 用户: ${this.backend.config.user?.account}\x1b[0m`); } + console.log('\x1b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m'); }); } @@ -147,9 +229,10 @@ class PixivServer { * 优雅关闭 */ async shutdown() { - console.log('正在关闭服务器...'); + console.log('\x1b[33m🔄 正在关闭服务器...\x1b[0m'); // 清理代理环境变量 proxyConfig.clearEnvironmentVariables(); + console.log('\x1b[32m✅ 服务器已关闭\x1b[0m'); process.exit(0); } } diff --git a/backend/start.js b/backend/start.js index f577ad5..7624eb7 100644 --- a/backend/start.js +++ b/backend/start.js @@ -31,35 +31,33 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; // 如果提供了代理端口,设置环境变量 if (cliOptions.proxyPort) { process.env.PROXY_PORT = cliOptions.proxyPort.toString(); - console.log(`📡 代理端口已设置为: ${cliOptions.proxyPort}`); + console.log(`\x1b[36m📡 代理端口已设置为: ${cliOptions.proxyPort}\x1b[0m`); } -console.log('🚀 启动 Pixiv 后端服务器...'); -console.log(`📊 环境: ${process.env.NODE_ENV}`); -console.log(`🌐 端口: ${process.env.PORT || 3000}`); +console.log('\x1b[35m🚀 启动 Pixiv 后端服务器...\x1b[0m'); // 创建服务器实例 const server = new PixivServer(); // 处理进程信号 process.on('SIGINT', async () => { - console.log('\n🛑 收到 SIGINT 信号,正在关闭服务器...'); + console.log('\n\x1b[33m🛑 收到 SIGINT 信号,正在关闭服务器...\x1b[0m'); await server.shutdown(); }); process.on('SIGTERM', async () => { - console.log('\n🛑 收到 SIGTERM 信号,正在关闭服务器...'); + console.log('\n\x1b[33m🛑 收到 SIGTERM 信号,正在关闭服务器...\x1b[0m'); await server.shutdown(); }); // 处理未捕获的异常 process.on('uncaughtException', (error) => { - console.error('❌ 未捕获的异常:', error); + console.error('\x1b[31m❌ 未捕获的异常:\x1b[0m', error); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { - console.error('❌ 未处理的 Promise 拒绝:', reason); + console.error('\x1b[31m❌ 未处理的 Promise 拒绝:\x1b[0m', reason); process.exit(1); }); @@ -67,6 +65,6 @@ process.on('unhandledRejection', (reason, promise) => { server.init() .then(() => server.start()) .catch((error) => { - console.error('❌ 服务器启动失败:', error); + console.error('\x1b[31m❌ 服务器启动失败:\x1b[0m', error); process.exit(1); }); \ No newline at end of file diff --git a/ui/dist.zip b/ui/dist.zip index 1780338..1ec9f7d 100644 Binary files a/ui/dist.zip and b/ui/dist.zip differ