全面审查优化: 43项修复(安全/性能/可靠性)+ 文档更新

🔴 P0 安全: .env入gitignore, CSP/HSTS, Logo安全(5MB限制+SVG消毒+SHA256), middleware权限收紧(VIP不能访问admin), 发布去重, GitHub认证, 删除危险API, skill-discoverer绕过审核修复, prisma默认连接修复
🔴 P0 可靠性: deepseek/github超时重试, 脚本层DeepSeek保护, 脚本启动验证, OAuth竞态修复
🔴 P0 性能: skill-discoverer N+1优化(↓94%), 后台API分页限制, getUserStats聚合优化
🟡 P1: 分类动态加载, 星级字段统一, fetch-logos并发Bug修复, 批量发布冲突不删除, check-tools重试, 前端空指针修复(13处), logo-fetcher日志, rate-limit清理, 公开API缓存
This commit is contained in:
ZhuiGuangAI Dev
2026-05-26 00:30:36 +08:00
parent 9bf3e7574a
commit e263e28c81
47 changed files with 1212 additions and 788 deletions
+81
View File
@@ -1,5 +1,86 @@
# 追光AI 变更日志
## 2026-05-25 全面审查优化(三轮扫描 + 43项修复)
### 🔴 P0 安全修复
- **.env入.gitignore**: `.env` 和 `.env.production` 加入忽略列表,创建 `.env.example` 模板文件
- **CSP/HSTS安全头**: next.config.mjs 添加 Content-Security-Policy、Strict-Transport-Security、Permissions-Policy
- **Logo安全加固**: 5MB大小限制 + SVG script/iframe/on-event 标签消毒 + MD5→SHA256
- **middleware权限收紧**: VIP用户不再能访问 /admin/* 和 /api/admin/*,仅admin角色可访问
- **单条发布去重**: pending-skills/[id]/publish 添加 name/sourceUrl/slug 三重去重检查,冲突返回409
- **Web更新星级GitHub认证**: update-stars API 添加 GITHUB_TOKEN 环境变量认证(限流60→5000次/小时)
- **删除危险API**: pending-skills/route.ts 的 DELETE 方法(原可无条件清空全表)已移除
- **skill-discoverer绕过审核**: Web自动发现统一改为写 pendingSkill 表(status:pending),不再跳过审核
- **prisma默认连接修复**: DATABASE_URL未设置时抛出明确错误,移除硬编码默认连接串
### 🔴 P0 可靠性修复
- **deepseek.ts超时重试**: OpenAI客户端添加 timeout:120000 + maxRetries:2,模型名改为 DEEPSEEK_MODEL 环境变量
- **github.ts超时重试**: Octokit 添加 timeout:30000,新增 withRetry 指数退避重试,403/404/422 不重试
- **脚本层DeepSeek保护**: 4个定时脚本(daily-discover/daily-news/task1/task6)添加 AbortSignal.timeout(120000) + withRetry 重试
- **脚本启动验证**: 定时脚本启动时验证 DEEPSEEK_API_KEY + DATABASE_URL 存在性
- **auth.ts OAuth竞态修复**: GitHub OAuth 并发创建用户时 P2002 唯一约束冲突自动回退 findFirst
### 🔴 P0 性能修复
- **skill-discoverer N+1优化**: 批量预加载 sourceUrl/slug/分类到内存 Set,DB查询从 ~360次 降至 ~22次(↓94%)
- **后台API分页限制**: 6个管理后台 API findMany 添加 take:500/1000 防全表扫描
- **getUserStats优化**: 改用 _count 聚合替代加载全量关联记录取 .length
### 🟡 P1 修复
- **分类动态加载**: discover-tools 页面分类列表从硬编码改为 /api/categories 动态加载
- **星级字段统一**: update-stars API 同时写入 rating + githubStars,统一提取 starsToRating() 函数
- **fetch-logos并发Bug修复**: processWithConcurrency 改用 Set<Promise> + then(cleanup) 模式
- **批量发布冲突不删除**: 冲突工具改为跳过标记,不再静默物理删除
- **check-tools API重试**: 添加指数退避重试(最多2次)
- **前端空指针修复**: 13处 email?.split / overallAvg?.toFixed / createdAt?.toLocaleDateString 可选链
- **logo-fetcher日志**: 9处空白 catch 块添加 console.warn 日志
- **rate-limit清理**: 每5分钟自动清理过期IP记录,防止内存无限增长
- **公开API缓存**: 5个公开API添加 Cache-Control 响应头(30s~300s分级缓存)
### 🔴 已修复的前台Bug
- **/reviews 评测列表不显示**: ReviewsList.tsx 添加 useEffect 在挂载时触发初始数据加载
### 📁 变更统计
| 类型 | 数量 |
|------|------|
| 修改文件 | ~55个 |
| 新增文件 | 1个(.env.example) |
| 修复问题 | 43项 |
| TypeScript检查 | 零错误通过 |
---
## 2026-05-25 页面重构 + HeroBanner五色方案
### 🎨 页面重构为三栏布局
- **统一布局**: `grid-cols-[208px_1fr_280px]` (左侧栏208px + 内容区 + 右侧栏280px)
- **/reviews**: HeroBanner + 左侧(外部热度排行+评测分值排行) + 右侧(五维模型+评测说明)
- **/community**: HeroBanner + 左侧(本月活跃用户+积分排行) + 右侧(社区指南)
- **/daily**: 保持原有三栏结构
### 🌈 HeroBanner 五色方案
- **重构组件**: 从三元表达式改为 `SCHEMES` 配置表,代码量从560行减至410行
- **5种配色**:
| 页面 | 配色 | 背景渐变色 | 高亮色 |
|------|------|-----------|--------|
| 首页 `/` | 🔵 cosmos 星空蓝 | `#1e3a5f → #1d4ed8` | `#93c5fd` |
| 技能 `/skills` | 🩷 crimson 玫红 | `#881337 → #e11d48` | `#fda4af` |
| 日报 `/daily` | 🟠 dawn 黎明金 | `#78350f → #a16207` | `#fcd34d` |
| 评测 `/reviews` | 🟣 aurora 极光紫 | `#4c1d95 → #6d28d9` | `#c4b5fd` |
| 社区 `/community` | 🟢 forest 森林绿 | `#064e3b → #047857` | `#6ee7b7` |
- **接口变更**: 旧 `highlightColor + starStyle` → 新 `colorScheme`,一个参数搞定
### 📁 新增/修改
| 文件 | 操作 | 说明 |
|------|------|------|
| `src/components/common/HeroBanner.tsx` | 重写 | 5色方案+配置表 |
| `src/app/reviews/page.tsx` | 重写 | 三栏布局+左侧排行 |
| `src/app/community/page.tsx` | 重写 | 三栏布局+左侧排行 |
| `src/app/community/CommunitySidebar.tsx` | 新增 | 活跃用户+积分排行 |
| `src/app/api/user/rankings/route.ts` | 新增 | 用户排行API |
| `src/components/layout/Header.tsx` | 修改 | 社区导航图标更换 |
---
## 2026-05-25 等级体系升级 + 论坛二级分类 + 会员空间
### 🔥 20级成长体系 (类似QQ)
+22 -3
View File
@@ -8,7 +8,7 @@
## 服务器与基础设施
- **域名**: www.zhuig.com (HTTPS,SSL证书自动续期)
- **云服务器**: 119.45.242.239 (登录名: ubuntu, 密钥: E:\ZG_Dev\pem\zg.pem)
- **云服务器**: 119.45.242.239 (登录名: **ubuntu**, 密钥: `Pem/zg.pem`)
- **数据库**: 阿里云RDS MySQL — rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306
- **Redis**: 云服务器上已有(Docker容器redis-cache:6379),与其他项目共用,有密码认证
- **本地Git同步目录**: K:\git-repos
@@ -16,6 +16,9 @@
- **部署目录**: /home/ubuntu/zhuiguang-ai
- **访问地址**: https://www.zhuig.com (HTTP自动跳转HTTPS)
- **注意事项**: 服务器有其他应用运行,部署时不可占用非8301-8310端口,不可影响其他服务
- **SSH连接示例**: `ssh -i "Pem/zg.pem" ubuntu@119.45.242.239`
- **PM2管理**: `pm2 list` / `pm2 restart zhuiguang-ai` / `pm2 save`
- **其他应用**: agent-system, nacos, zhuiguang-quant (部署时请勿影响)
## 技术栈
- Next.js 14 (App Router) + TypeScript
@@ -60,8 +63,8 @@
- 批量操作: body中传 `ids` 数组
## 页面路由
- 前台: `/`, `/tools`, `/tools/[slug]`, `/categories/[slug]`, `/skills`, `/skills/[slug]`, `/login`, `/user`, `/user/favorites`
- 后台: `/admin/login`, `/admin/pending`, `/admin/pending-skills`, `/admin/tools`, `/admin/skills`, `/admin/categories`, `/admin/skill-categories`, `/admin/discover-tools`, `/admin/check-tools`, `/admin/discover-skills`, `/admin/update-skills`, `/admin/discover-news`, `/admin/system-config`
- 前台: `/`, `/tools`, `/tools/[slug]`, `/categories/[slug]`, `/skills`, `/skills/[slug]`, `/login`, `/user`, `/user/favorites`, `/user/[id]`(会员空间), `/user/collections`, `/daily`, `/reviews`, `/community`, `/community/[category]`, `/community/topic/[id]`
- 后台: `/admin/login`, `/admin/pending`, `/admin/pending-skills`, `/admin/tools`, `/admin/skills`, `/admin/categories`, `/admin/skill-categories`, `/admin/discover-tools`, `/admin/check-tools`, `/admin/discover-skills`, `/admin/update-skills`, `/admin/discover-news`, `/admin/system-config`, `/admin/tasks`, `/admin/tasks/logs`, `/admin/tasks/[taskKey]`, `/admin/reviews`
## 五大操作指令
@@ -169,3 +172,19 @@
- Chart.js组件需用dynamic import + ssr: false,不支持服务端渲染
- Prisma 7.8需通过PrismaMariaDb适配器初始化,不能直接new PrismaClient()
- 服务器环境SSL证书问题: 运行脚本需设置$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
### 6. 安全原则
- 敏感信息(密钥、密码、Token)必须使用环境变量,禁止硬编码
- `.env` 文件已被加入 `.gitignore`,仅 `.env.example` 模板可提交
- HTTP 响应必须包含安全头:CSP、HSTS、X-Content-Type-Options、X-Frame-Options
- 文件上传/下载必须限制大小(最大 5MB)和类型,SVG 内容需消毒 script/iframe/on-event 标签
- Logo 文件名使用 SHA256 哈希(不使用 MD5)
- VIP 用户不能访问管理后台(/admin/* 和 /api/admin/*)
### 7. 可靠性原则
- 所有外部 API 调用(GitHub、DeepSeek 等)必须设置超时和重试
- OpenAI/DeepSeek 客户端配置:`timeout: 120000`, `maxRetries: 2`
- Octokit 配置:`request.timeout: 30000`,配合 withRetry 指数退避重试
- 定时脚本启动时必须验证必需环境变量(DEEPSEEK_API_KEY、DATABASE_URL)
- DeepSeek 模型名使用环境变量 `DEEPSEEK_MODEL`(默认 `deepseek-v4-pro`)
- OAuth 用户创建需处理 P2002 唯一约束冲突竞态