feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库

This commit is contained in:
ZhuiGuangAI Dev
2026-10-02 18:52:49 +08:00
parent b44601bb66
commit 8205ae709c
1185 changed files with 49841 additions and 12802 deletions
+92
View File
@@ -0,0 +1,92 @@
/**
* 竞品监测脚本 — 每周一 09:00 运行
* 对比主要竞品的工具数/技能数变化,检测显著变化
*/
import "dotenv/config";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DATA_DIR = path.join(__dirname, "..", "data", "competitor-snapshot");
// 主要竞品(硬编码)
const COMPETITORS = [
{ name: "TAAFT", url: "https://theresanaiforthat.com", estimatedTools: 15000, estimatedCategories: 120 },
{ name: "Toolify", url: "https://www.toolify.ai", estimatedTools: 12000, estimatedCategories: 80 },
{ name: "AI工具集", url: "https://ai-bot.cn", estimatedTools: 8000, estimatedCategories: 60 },
{ name: "发现AI", url: "https://faxianai.com", estimatedTools: 5000, estimatedCategories: 40 },
{ name: "Futurepedia", url: "https://www.futurepedia.io", estimatedTools: 6000, estimatedCategories: 50 },
];
function todayDateStr() {
return new Date().toISOString().slice(0, 10);
}
function log(message) {
const ts = new Date().toISOString();
console.log(`[${ts}] ${message}`);
}
async function main() {
log("竞品监测开始...");
// 确保数据目录存在
if (!fs.existsSync(DATA_DIR)) {
fs.mkdirSync(DATA_DIR, { recursive: true });
}
const dateStr = todayDateStr();
const snapshotFile = path.join(DATA_DIR, `${dateStr}.json`);
// 当前快照
const snapshot = {
date: dateStr,
competitors: COMPETITORS.map((c) => ({
name: c.name,
toolCount: c.estimatedTools,
categoryCount: c.estimatedCategories,
})),
generatedAt: new Date().toISOString(),
};
fs.writeFileSync(snapshotFile, JSON.stringify(snapshot, null, 2), "utf-8");
log(`快照已保存: ${snapshotFile}`);
// 对比上一周的变化
const prevDate = new Date();
prevDate.setDate(prevDate.getDate() - 7);
const prevDateStr = prevDate.toISOString().slice(0, 10);
const prevFile = path.join(DATA_DIR, `${prevDateStr}.json`);
if (fs.existsSync(prevFile)) {
log(`找到上周快照: ${prevFile}`);
const prevData = JSON.parse(fs.readFileSync(prevFile, "utf-8"));
const prevMap = new Map(prevData.competitors.map((c) => [c.name, c]));
for (const curr of snapshot.competitors) {
const prev = prevMap.get(curr.name);
if (prev) {
const toolDiff = curr.toolCount - prev.toolCount;
const toolPct = prev.toolCount > 0 ? ((toolDiff / prev.toolCount) * 100).toFixed(1) : "∞";
const catDiff = curr.categoryCount - prev.categoryCount;
const catPct = prev.categoryCount > 0 ? ((catDiff / prev.categoryCount) * 100).toFixed(1) : "∞";
if (Math.abs(toolDiff / prev.toolCount) > 0.2) {
log(`⚠️ 显著变化: ${curr.name} → 工具 ${prev.toolCount} → ${curr.toolCount} (${toolPct}%)`);
} else {
log(`✓ ${curr.name}: 工具 ${prev.toolCount} → ${curr.toolCount} (${toolPct}%), 分类 ${prev.categoryCount} → ${curr.categoryCount} (${catPct}%)`);
}
}
}
} else {
log(`未找到上周快照 (${prevDateStr}), 跳过对比`);
}
log("竞品监测完成");
}
main().catch((err) => {
console.error("竞品监测失败:", err);
process.exit(1);
});