diff --git a/public/lib/bg-change.js b/public/lib/bg-change.js index 168a16a..b5db4ba 100644 --- a/public/lib/bg-change.js +++ b/public/lib/bg-change.js @@ -383,11 +383,11 @@ function createMockWallpaperApi() { // 替换原生fetch以模拟API调用 window.originalFetch = window.fetch - window.fetch = function (url) { + window.fetch = function (url, opts = {}) { if (url === "/api/random-wallpaper") { return window.fetchRandomWallpaper() } - return window.originalFetch(url) + return window.originalFetch(...arguments) } console.log("模拟壁纸API已启动") diff --git a/src/logger.js b/src/logger.js index 8e5285e..06392df 100644 --- a/src/logger.js +++ b/src/logger.js @@ -1,22 +1,26 @@ -import log4js from "log4js" + +import log4js from "log4js"; + +// 日志目录可通过环境变量 LOG_DIR 配置,默认 logs +const LOG_DIR = process.env.LOG_DIR || "logs"; log4js.configure({ appenders: { - // debug: { - // type: "file", - // filename: "logs/debug.log", - // maxLogSize: 102400, - // pattern: "-yyyy-MM-dd.log", - // alwaysIncludePattern: true, - // backups: 3, - // layout: { - // type: 'pattern', - // pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', - // }, - // }, all: { type: "file", - filename: "logs/all.log", + filename: `${LOG_DIR}/all.log`, + maxLogSize: 102400, + pattern: "-yyyy-MM-dd.log", + alwaysIncludePattern: true, + backups: 3, + layout: { + type: 'pattern', + pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', + }, + }, + error: { + type: "file", + filename: `${LOG_DIR}/error.log`, maxLogSize: 102400, pattern: "-yyyy-MM-dd.log", alwaysIncludePattern: true, @@ -26,21 +30,9 @@ log4js.configure({ pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', }, }, - // error: { - // type: "file", - // filename: "logs/error.log", - // maxLogSize: 102400, - // pattern: "-yyyy-MM-dd.log", - // alwaysIncludePattern: true, - // backups: 3, - // layout: { - // type: 'pattern', - // pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', - // }, - // }, jobs: { type: "file", - filename: "logs/jobs.log", + filename: `${LOG_DIR}/jobs.log`, maxLogSize: 102400, pattern: "-yyyy-MM-dd.log", alwaysIncludePattern: true, @@ -50,18 +42,6 @@ log4js.configure({ pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', }, }, - // site: { - // type: "file", - // filename: "logs/site.log", - // maxLogSize: 102400, - // pattern: "-yyyy-MM-dd.log", - // alwaysIncludePattern: true, - // backups: 3, - // layout: { - // type: 'pattern', - // pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', - // }, - // }, console: { type: "console", layout: { @@ -71,19 +51,13 @@ log4js.configure({ }, }, categories: { - jobs: { appenders: ["console", "jobs"], level: "ALL" }, - // site: { appenders: ["site"], level: "ALL" }, - // console: { appenders: ["console"], level: "ALL" }, - // error: { appenders: ["console", "error"], level: "error" }, - default: { appenders: ["console", "all"], level: "ALL" }, - // debug: { appenders: ["debug"], level: "debug" }, + jobs: { appenders: ["console", "jobs"], level: "info" }, + error: { appenders: ["console", "error"], level: "error" }, + default: { appenders: ["console", "all", "error"], level: "all" }, }, -}) +}); -// 导出常用logger实例,便于直接引用 -export const logger = log4js.getLogger(); -// export const debugLogger = log4js.getLogger('debug'); +// 导出常用 logger 实例,便于直接引用 +export const logger = log4js.getLogger(); // default export const jobLogger = log4js.getLogger('jobs'); -// export const errorLogger = log4js.getLogger('error'); -// export const siteLogger = log4js.getLogger('site'); -// export const consoleLogger = log4js.getLogger('console'); +export const errorLogger = log4js.getLogger('error'); diff --git a/src/utils/ForRegister.js b/src/utils/ForRegister.js index 21a1df7..9de0992 100644 --- a/src/utils/ForRegister.js +++ b/src/utils/ForRegister.js @@ -2,6 +2,7 @@ // 兼容传统 routes 方式和自动注册 controller 方式 import fs from "fs" import path from "path" +import { logger } from "@/logger.js" // 保证不会被摇树(tree-shaking),即使在生产环境也会被打包 if (import.meta.env.PROD) { @@ -21,58 +22,80 @@ if (import.meta.env.PROD) { */ export function autoRegisterControllers(app, controllersDir = path.resolve(__dirname, "../controllers")) { let allRouter = [] + async function scan(dir, routePrefix = "") { - for (const file of fs.readdirSync(dir)) { - const fullPath = path.join(dir, file) - const stat = fs.statSync(fullPath) - if (stat.isDirectory()) { - await scan(fullPath, routePrefix + "/" + file) - } else if (file.endsWith("Controller.js")) { - let controller - try { - controller = require(fullPath) - } catch (e) { - controller = (await import(fullPath)).default - } - const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller - if (typeof routes === "function") { - allRouter.push(routes()) + try { + for (const file of fs.readdirSync(dir)) { + const fullPath = path.join(dir, file) + const stat = fs.statSync(fullPath) + + if (stat.isDirectory()) { + await scan(fullPath, routePrefix + "/" + file) + } else if (file.endsWith("Controller.js")) { + try { + // 使用动态import替代require,确保ES模块兼容性 + const controllerModule = await import(fullPath) + const controller = controllerModule.default || controllerModule + + if (!controller) { + logger.warn(`Controller ${file} 没有默认导出`) + continue + } + + const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller + + if (typeof routes === "function") { + try { + const router = routes() + if (router && typeof router.middleware === "function") { + allRouter.push(router) + logger.info(`成功注册控制器: ${file}`) + } else { + logger.warn(`Controller ${file} 的 createRoutes 返回的不是有效的路由器`) + } + } catch (error) { + logger.error(`执行 Controller ${file} 的 createRoutes 时出错:`, error.message) + } + } else { + logger.warn(`Controller ${file} 没有 createRoutes 方法`) + } + } catch (importError) { + logger.error(`导入 Controller ${file} 失败:`, importError.message) + } } } + } catch (error) { + logger.error(`扫描目录 ${dir} 时出错:`, error.message) } } - ;(async () => { - await scan(controllersDir) - // TODO: 存在问题:每个Controller都是有顺序的,如果其中一个Controller没有next方法,可能会导致后续的Controller无法执行 - allRouter.forEach(router => { - app.use(router.middleware()) - }) - // // 聚合中间件:只分发到匹配的router - // app.use(async (ctx, next) => { - // let matched = false - // for (const router of allRouter) { - // // router._matchRoute 只在 router.js 内部,需暴露或用 middleware 包一层 - // if (typeof router._matchRoute === "function") { - // const route = router._matchRoute(ctx.method.toLowerCase(), ctx.path) - // if (route) { - // matched = true - // await router.middleware()(ctx, next) - // break // 命中一个即停止 - // } - // } else { - // // fallback: 直接尝试middleware,若未命中会自动next - // const before = ctx.status - // await router.middleware()(ctx, next) - // if (ctx.status !== before) { - // matched = true - // break - // } - // } - // } - // if (!matched) { - // await next() - // } - // }) + // 使用立即执行的异步函数来注册路由 + (async () => { + try { + await scan(controllersDir) + + if (allRouter.length === 0) { + logger.warn("没有找到任何可注册的控制器") + return + } + + logger.info(`找到 ${allRouter.length} 个控制器,开始注册路由`) + + // 按顺序注册路由,确保中间件执行顺序 + for (let i = 0; i < allRouter.length; i++) { + const router = allRouter[i] + try { + app.use(router.middleware()) + logger.debug(`路由 ${i + 1}/${allRouter.length} 注册成功`) + } catch (error) { + logger.error(`注册路由 ${i + 1}/${allRouter.length} 失败:`, error.message) + } + } + + logger.info("所有路由注册完成") + + } catch (error) { + logger.error("自动注册控制器过程中发生错误:", error.message) + } })() }