全项目扫描修复: Docker数据卷修复+安全requireAdmin+12页SEO+API白名单+脚本超时+常量提取+假数据删除

This commit is contained in:
ZhuiGuangAI Dev
2026-06-12 17:27:47 +08:00
parent 464924aea0
commit 4c325c8699
454 changed files with 33647 additions and 980 deletions
+102
View File
@@ -0,0 +1,102 @@
// 健康检查脚本:扫描所有定时任务最近一次执行情况
import { PrismaClient } from "@prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import "dotenv/config";
const base = process.env.DATABASE_URL.replace("mysql://", "mariadb://");
const sep = base.includes("?") ? "&" : "?";
const connectionString = `${base}${sep}connection_limit=2&pool_timeout=10`;
const adapter = new PrismaMariaDb(connectionString);
const prisma = new PrismaClient({ adapter });
async function main() {
console.log("========== 任务调度健康检查 ==========\n");
// 1. 任务配置
const configs = await prisma.taskConfig.findMany({ orderBy: { taskKey: "asc" } });
console.log("--- 任务配置 ---");
console.log(`共 ${configs.length} 条配置`);
for (const c of configs) {
console.log(` [${c.enabled ? "●" : "○"}] ${c.taskKey.padEnd(30)} cron=${c.cronExpr || "—"} ${c.taskName}`);
}
// 2. 最近 7 天的执行记录
const since = new Date(Date.now() - 7 * 24 * 3600 * 1000);
const logs = await prisma.taskLog.findMany({
where: { startedAt: { gte: since } },
orderBy: { startedAt: "desc" },
});
console.log(`\n--- 最近 7 天日志(${logs.length} 条) ---`);
const byKey = new Map();
for (const l of logs) {
if (!byKey.has(l.taskKey)) byKey.set(l.taskKey, []);
byKey.get(l.taskKey).push(l);
}
for (const [key, list] of byKey.entries()) {
const success = list.filter((l) => l.status === "completed").length;
const failed = list.filter((l) => l.status === "failed").length;
const last = list[0];
const lastDate = new Date(last.startedAt).toLocaleString("zh-CN");
console.log(` ${key.padEnd(30)} 共${list.length}次 成功${success} 失败${failed} 最近=${lastDate} status=${last.status}`);
}
// 3. 任何"从未执行"的任务
console.log("\n--- 检查哪些 taskKey 已配置但从未执行 ---");
const executedKeys = new Set(logs.map((l) => l.taskKey));
const allExpectedKeys = new Set([
...configs.map((c) => c.taskKey),
"task1-discover-tools",
"task3-check-tools",
"task4-discover-skills",
"task5-update-stars",
"task6-review-hot",
"task7-news-to-community",
"daily-news",
"bot-activity",
"bot-affinity-update",
"bot-feedback-loop",
"bot-weekly-review",
"bot-skill-crystallize",
]);
const knownButNeverRun = [...allExpectedKeys].filter((k) => !executedKeys.has(k));
console.log("从未执行:", knownButNeverRun.length ? knownButNeverRun.join(", ") : "无");
// 4. bot 体系健康
console.log("\n--- Bot 体系健康 ---");
const totalBots = await prisma.user.count({ where: { isBot: true } });
const totalTopicsByBots = await prisma.forumTopic.count({ where: { user: { isBot: true } } });
const totalPostsByBots = await prisma.forumPost.count({ where: { user: { isBot: true } } });
const totalMemories = await prisma.botMemory.count();
const totalBotConfigs = await prisma.botConfig.count();
const lastBotTopic = await prisma.forumTopic.findFirst({
where: { user: { isBot: true } },
orderBy: { createdAt: "desc" },
select: { createdAt: true, title: true },
});
console.log(` Bot 用户总数: ${totalBots}`);
console.log(` BotConfig 数: ${totalBotConfigs}`);
console.log(` BotMemory 数: ${totalMemories}`);
console.log(` Bot 发帖数: ${totalTopicsByBots}`);
console.log(` Bot 回复数: ${totalPostsByBots}`);
if (lastBotTopic) {
const hoursAgo = (Date.now() - new Date(lastBotTopic.createdAt).getTime()) / 3600000;
console.log(` 最近 Bot 帖: ${lastBotTopic.title.substring(0, 40)}... (${hoursAgo.toFixed(1)} 小时前)`);
} else {
console.log(" 最近 Bot 帖: 无");
}
// 5. 最近失败的详情
const recentFailed = logs.filter((l) => l.status === "failed").slice(0, 5);
console.log(`\n--- 最近失败任务 (${recentFailed.length}) ---`);
for (const f of recentFailed) {
console.log(` ${f.taskKey} @ ${new Date(f.startedAt).toLocaleString("zh-CN")}`);
if (f.error) console.log(` ${f.error.substring(0, 200)}`);
}
await prisma.$disconnect();
}
main().catch((e) => {
console.error(e);
process.exit(1);
});