Browse Source

修复模拟壁纸API的fetch函数,支持传递选项参数

feat/collect
谢亚昕 2 days ago
parent
commit
9feb236a34
  1. 4
      public/lib/bg-change.js
  2. 76
      src/logger.js
  3. 93
      src/utils/ForRegister.js

4
public/lib/bg-change.js

@ -383,11 +383,11 @@ function createMockWallpaperApi() {
// 替换原生fetch以模拟API调用 // 替换原生fetch以模拟API调用
window.originalFetch = window.fetch window.originalFetch = window.fetch
window.fetch = function (url) { window.fetch = function (url, opts = {}) {
if (url === "/api/random-wallpaper") { if (url === "/api/random-wallpaper") {
return window.fetchRandomWallpaper() return window.fetchRandomWallpaper()
} }
return window.originalFetch(url) return window.originalFetch(...arguments)
} }
console.log("模拟壁纸API已启动") console.log("模拟壁纸API已启动")

76
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({ log4js.configure({
appenders: { 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: { all: {
type: "file", 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, maxLogSize: 102400,
pattern: "-yyyy-MM-dd.log", pattern: "-yyyy-MM-dd.log",
alwaysIncludePattern: true, alwaysIncludePattern: true,
@ -26,21 +30,9 @@ log4js.configure({
pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', 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: { jobs: {
type: "file", type: "file",
filename: "logs/jobs.log", filename: `${LOG_DIR}/jobs.log`,
maxLogSize: 102400, maxLogSize: 102400,
pattern: "-yyyy-MM-dd.log", pattern: "-yyyy-MM-dd.log",
alwaysIncludePattern: true, alwaysIncludePattern: true,
@ -50,18 +42,6 @@ log4js.configure({
pattern: '[%d{yyyy-MM-dd hh:mm:ss}] [%p] %m', 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: { console: {
type: "console", type: "console",
layout: { layout: {
@ -71,19 +51,13 @@ log4js.configure({
}, },
}, },
categories: { categories: {
jobs: { appenders: ["console", "jobs"], level: "ALL" }, jobs: { appenders: ["console", "jobs"], level: "info" },
// site: { appenders: ["site"], level: "ALL" }, error: { appenders: ["console", "error"], level: "error" },
// console: { appenders: ["console"], level: "ALL" }, default: { appenders: ["console", "all", "error"], level: "all" },
// error: { appenders: ["console", "error"], level: "error" },
default: { appenders: ["console", "all"], level: "ALL" },
// debug: { appenders: ["debug"], level: "debug" },
}, },
}) });
// 导出常用 logger 实例,便于直接引用 // 导出常用 logger 实例,便于直接引用
export const logger = log4js.getLogger(); export const logger = log4js.getLogger(); // default
// export const debugLogger = log4js.getLogger('debug');
export const jobLogger = log4js.getLogger('jobs'); export const jobLogger = log4js.getLogger('jobs');
// export const errorLogger = log4js.getLogger('error'); export const errorLogger = log4js.getLogger('error');
// export const siteLogger = log4js.getLogger('site');
// export const consoleLogger = log4js.getLogger('console');

93
src/utils/ForRegister.js

@ -2,6 +2,7 @@
// 兼容传统 routes 方式和自动注册 controller 方式 // 兼容传统 routes 方式和自动注册 controller 方式
import fs from "fs" import fs from "fs"
import path from "path" import path from "path"
import { logger } from "@/logger.js"
// 保证不会被摇树(tree-shaking),即使在生产环境也会被打包 // 保证不会被摇树(tree-shaking),即使在生产环境也会被打包
if (import.meta.env.PROD) { if (import.meta.env.PROD) {
@ -21,58 +22,80 @@ if (import.meta.env.PROD) {
*/ */
export function autoRegisterControllers(app, controllersDir = path.resolve(__dirname, "../controllers")) { export function autoRegisterControllers(app, controllersDir = path.resolve(__dirname, "../controllers")) {
let allRouter = [] let allRouter = []
async function scan(dir, routePrefix = "") { async function scan(dir, routePrefix = "") {
try {
for (const file of fs.readdirSync(dir)) { for (const file of fs.readdirSync(dir)) {
const fullPath = path.join(dir, file) const fullPath = path.join(dir, file)
const stat = fs.statSync(fullPath) const stat = fs.statSync(fullPath)
if (stat.isDirectory()) { if (stat.isDirectory()) {
await scan(fullPath, routePrefix + "/" + file) await scan(fullPath, routePrefix + "/" + file)
} else if (file.endsWith("Controller.js")) { } else if (file.endsWith("Controller.js")) {
let controller
try { try {
controller = require(fullPath) // 使用动态import替代require,确保ES模块兼容性
} catch (e) { const controllerModule = await import(fullPath)
controller = (await import(fullPath)).default const controller = controllerModule.default || controllerModule
if (!controller) {
logger.warn(`Controller ${file} 没有默认导出`)
continue
} }
const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller
if (typeof routes === "function") { if (typeof routes === "function") {
allRouter.push(routes()) 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 () => { // 使用立即执行的异步函数来注册路由
(async () => {
try {
await scan(controllersDir) await scan(controllersDir)
// TODO: 存在问题:每个Controller都是有顺序的,如果其中一个Controller没有next方法,可能会导致后续的Controller无法执行
allRouter.forEach(router => { 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()) app.use(router.middleware())
}) logger.debug(`路由 ${i + 1}/${allRouter.length} 注册成功`)
// // 聚合中间件:只分发到匹配的router } catch (error) {
// app.use(async (ctx, next) => { logger.error(`注册路由 ${i + 1}/${allRouter.length} 失败:`, error.message)
// let matched = false }
// for (const router of allRouter) { }
// // router._matchRoute 只在 router.js 内部,需暴露或用 middleware 包一层
// if (typeof router._matchRoute === "function") { logger.info("所有路由注册完成")
// const route = router._matchRoute(ctx.method.toLowerCase(), ctx.path)
// if (route) { } catch (error) {
// matched = true logger.error("自动注册控制器过程中发生错误:", error.message)
// 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()
// }
// })
})() })()
} }

Loading…
Cancel
Save