2026-05-25: 等级体系升级(20级)+论坛二级分类+会员空间
This commit is contained in:
+72
-255
@@ -1,275 +1,92 @@
|
||||
# 追光AI 变更日志
|
||||
|
||||
## v0.11.1 (2026-05-22) - AI发现管线质量优化
|
||||
## 2026-05-25 等级体系升级 + 论坛二级分类 + 会员空间
|
||||
|
||||
### 全链路测试
|
||||
- 跑通全部AI自动化管线:GitHub搜索 → DeepSeek评测 → 入库 → 内容生成
|
||||
- 2个脚本(automatic-review + daily-discover) + 4个API端点全部验证通过
|
||||
- 连测创建12条技能+评测记录,DeepSeek生成1篇日报+长文+视频脚本+社交卡片
|
||||
### 🔥 20级成长体系 (类似QQ)
|
||||
- **从4级扩展到20级**: LV01(0分) → LV20(50000分)
|
||||
- **等级图标**: ⭐(初级) → ⭐⭐⭐(中级) → 🌟(高级) → 🌟🌟(精英) → 🌟🌟🌟(大师)
|
||||
- **旧等级迁移**: BRONZE→LV01, SILVER→LV03, GOLD→LV06, PLATINUM→LV10
|
||||
- `src/lib/level-config.ts` — 20级完整配置(含每日限额表)
|
||||
- **迁移脚本**: `scripts/run-migration-manual.mjs` (绕过shadow DB问题)
|
||||
|
||||
### 质量过滤修复
|
||||
- **非AI项目过滤**: auto-review.mjs + daily-discover.mjs 新增 `isValidAIProject()` 函数
|
||||
- 关键词过滤: `book/guide/tutorial/awesome/interview/notes/handbook/cheatsheet/roadmap/curated-list` 等
|
||||
- 语言过滤: 纯Markdown/HTML文档Repo(Stars<5000)自动拒绝
|
||||
- 主题过滤: 有GitHub Topics的Repo必须包含AI相关Topic(ai/llm/rag/agent/gpt等)
|
||||
- 清理5条误入库非AI数据:AgentGuide、JavaGuide、pathway、StableDiffusionBook、Claude-Code-Everything
|
||||
### 🔥 论坛二级分类结构
|
||||
- **ForumCategory自引用关系**: parent/children (CategoryHierarchy)
|
||||
- **6个父分类 + 24个子分类**:
|
||||
- 综合讨论区 → 新手入门/AI资讯/观点讨论
|
||||
- AI工具 → 聊天写作/图像创作/视频音频/代码编程/效率办公/数据分析/教育学习
|
||||
- 开源技能 → LLM框架/Agent框架/RAG技术/模型训练/部署推理/多模态/数据工程
|
||||
- 技术深度 → 算法原理/模型评测/安全对齐/硬件加速
|
||||
- 教程与分享 → 入门教程/实战项目/最佳实践
|
||||
- 社区互动 → 求助问答/求职招聘/闲聊灌水/反馈建议
|
||||
- **修复脚本**: `scripts/fix-forum-categories.mjs` (修正孤立子分类parentId)
|
||||
- `/community` 首页更新为显示二级分类结构
|
||||
|
||||
### JSON解析健壮性
|
||||
- 新增 `extractJSON()` 统一工具函数 → `src/lib/utils.ts`
|
||||
- 支持markdown代码块包裹(`\`\`\`json...\`\`\``)、花括号/方括号容错
|
||||
- 替换 deepseek.ts、auto-review.mjs、daily-discover.mjs、daily-reports/generate 的旧解析逻辑
|
||||
- 新增 `scripts/test-content-generation.mjs` 全管线测试脚本
|
||||
### 🆕 会员个人空间
|
||||
- `/user/[id]` — 会员空间页面(资料/统计/话题/评论)
|
||||
- **分享功能**: `ShareButton` 组件(原生API/Twitter/QQ/复制链接)
|
||||
- **bio字段**: 用户个人简介,支持编辑(最多500字符)
|
||||
- `/user` 页面新增bio编辑区域
|
||||
|
||||
### 新增脚本
|
||||
- `scripts/cleanup-non-ai.mjs` — 一键清理误入库非AI技能数据
|
||||
### 🔧 技术修复
|
||||
- 修复所有旧等级引用 (BRONZE → LV01)
|
||||
- 修复 ShareButton 构建错误 (Twitter图标 → Link图标)
|
||||
- 修复 LevelProgress 动态颜色逻辑 (基于等级数字计算)
|
||||
- 数据库迁移标记为已应用: `20260525000000_expand_user_levels`
|
||||
|
||||
---
|
||||
|
||||
## v0.11.0 (2026-05-22) - 权限体系重构
|
||||
## 2026-05-24 会员功能优化 + 追光会论坛上线
|
||||
|
||||
### 架构变更
|
||||
- **新增数据模型**: `Role`(角色), `Permission`(权限点), `RolePermission`(角色-权限关联) 三张表
|
||||
- **User 模型**: 新增 `roleId` 字段关联 `Role`,与原有 `role` 字符串字段并行(向后兼容)
|
||||
- 默认角色:**超级管理员**(Admin, 全部53权限)、**VIP成员**(Vip, 19个精选权限)
|
||||
### 🆕 积分体系
|
||||
- **PointsHistory** 数据模型 — 记录所有积分变动,含原因/详情/关联信息
|
||||
- **4级会员系统**: 青铜🥉(0分) → 白银🥈(100分) → 黄金🥇(500分) → 铂金💎(2000分)
|
||||
- **积分规则**: 评论+5/被赞+2/发帖+10/回复+5/评价+8,含每日上限防刷分
|
||||
- `src/lib/level-config.ts` — 客户端安全等级配置(无 Prisma 依赖)
|
||||
- `src/lib/points-reward.ts` — 积分奖励引擎(rewardPoints / getUserStats / getUserPointsHistory)
|
||||
- `/api/user/points` — 积分统计 + 历史查询 API
|
||||
|
||||
### 权限体系
|
||||
- **53个精细化权限点**,按页面分组管理:
|
||||
- 工具管理 14项 · 技能库 12项 · 评测管理 8项
|
||||
- AI发现 7项 · 内容管理 8项 · 系统管理 4项
|
||||
- 所有后台按钮/操作均已对应权限点,可逐个勾选控制
|
||||
### 🆕 追光会(论坛)
|
||||
- **3个新页面**: /community(首页)、/community/[category](板块)、/community/topic/[id](话题详情)
|
||||
- **8个论坛板块**: 综合讨论/AI工具推荐/技能分享/技术探讨/教程指南/反馈建议/求职招聘/闲聊灌水
|
||||
- **5个论坛API**: 分类/话题(CRUD)/回复(CRUD) 共10个端点
|
||||
- **4个论坛组件**: ForumBoard / ForumTopicCard / ForumEditor / NotificationBell
|
||||
- **种子脚本**: `scripts/seed-forum-categories.mjs`
|
||||
|
||||
### 新增页面
|
||||
- **`/admin/roles` 角色权限管理**: 左侧角色列表 + 右侧按分组的权限勾选网格
|
||||
- 新建/删除自定义角色(系统角色受保护)
|
||||
- 分组全选/取消全选
|
||||
- 保存按钮实时同步到数据库
|
||||
### 🆕 评论系统(全新实现)
|
||||
- `/api/comments` — GET获取(含用户等级/积分)+ POST创建(自动积分奖励+通知)
|
||||
- `/api/comments/[id]/like` — 点赞/取消点赞(切换模式,+2分+通知)
|
||||
- `CommentCard` — 评论卡片(等级徽章/评分/点赞/嵌套回复)
|
||||
- `CommentThread` — 评论列表(分页/排序/回复面板)
|
||||
|
||||
### 新增 API
|
||||
- `GET/POST /api/admin/roles` — 角色列表/创建
|
||||
- `PUT/DELETE /api/admin/roles/[id]` — 角色编辑/删除
|
||||
- `GET /api/admin/permissions` — 全部权限点列表
|
||||
- `GET /api/admin/user-permissions` — 用户权限查询(支持roleId/userId/当前用户)
|
||||
### 🆕 通知系统
|
||||
- `/api/notifications` — GET获取(含未读数)+ PUT标记已读
|
||||
- `NotificationBell` — 导航栏通知铃铛(红点/下拉面板/自动已读)
|
||||
- 自动触发: 评论回复/评论点赞/话题回复
|
||||
|
||||
### 鉴权升级
|
||||
- **middleware.ts**: 从硬编码 `role==="admin"` 改为认证检查 + 路由层委派
|
||||
- **admin-auth.ts**: `requireAdmin()` 兼容旧 `role` 字符串 + 新 `roleId` 关联角色双重逻辑
|
||||
- 新增 `requirePermission(key)` — 细粒度权限点校验
|
||||
- 新增 `getAllUserPermissions()` — 获取当前用户全部权限集合
|
||||
### 🆕 会员UI组件
|
||||
- `MemberBadge` — 等级徽章(3种尺寸,支持显示/隐藏积分)
|
||||
- `LevelProgress` — 等级进度条(当前等级/下一级/进度百分比)
|
||||
|
||||
### 前端工具
|
||||
- 新增 `usePermission()` hook — 提供 `can(key)`, `canAny(keys)`, `canAll(keys)` 方法
|
||||
- 侧边栏新增"角色权限"菜单入口
|
||||
|
||||
### 种子脚本
|
||||
- `scripts/seed-permissions.mjs` — 一键初始化全部权限点+角色
|
||||
|
||||
---
|
||||
|
||||
## v0.10.1 (2026-05-22) - 全面修复与优化
|
||||
|
||||
### 安全修复
|
||||
- **Admin API 鉴权增强**: 中间件matcher新增`/api/admin/:path*`路由保护,未登录或非管理员角色返回403
|
||||
- 所有关键admin路由已内置`requireAdmin()`双重校验(中间件+路由层防御深度)
|
||||
|
||||
### Bug 修复
|
||||
- **Category ID 动态化**: `skill-discoverer.ts`、`daily-discover.mjs`、`auto-review.mjs`三个文件的硬编码Category ID(120-127)替换为数据库查询+关键词匹配,消除分类错配风险
|
||||
- **reviews统计卡片**: 修复评测管理页面统计(已发布/草稿/平均评分)只显示当前页数据的问题,改为从全局groupBy统计获取
|
||||
- **内容生成日志完善**: `/api/admin/reviews/[id]/generate`成功和失败均写入`ReviewGenerationLog`
|
||||
|
||||
### 功能增强
|
||||
- **待审核技能编辑增强**: 编辑对话框新增"功能特性(JSON)"和"标签(逗号分隔)"输入框,支持直接编辑上传
|
||||
- **已发布技能编辑增强**: 编辑对话框新增"分类"下拉选择、"功能特性(JSON)"、"标签"字段,功能对齐待审核页面
|
||||
- **日报AI一键生成**: 新增`/api/admin/daily-reports/generate`端点,前端新增"一键AI生成"按钮,直接调用DeepSeek生成日报并自动填充表单,替代原有的"复制提示词→粘贴JSON"手动流程
|
||||
|
||||
### 内部改进
|
||||
- `ReviewGenerationLog`确认已在`skill-discoverer.ts`和两个脚本中正常使用,非僵尸表
|
||||
- 三个脚本文件统一使用数据库查询获取分类ID,消除代码不一致
|
||||
|
||||
---
|
||||
|
||||
## v0.10.0 (2026-05-20) - 五维评测系统
|
||||
|
||||
### 新增
|
||||
- **数据库扩展**: SkillReview模型(五维评测)、ReviewGenerationLog模型(评测日志)、ReviewStatus枚举(DRAFT/PUBLISHED/REJECTED/OUTDATED)
|
||||
- **Skill模型扩展**: 新增lastReviewedAt(最近评测时间)、githubStarsHistory(Star历史)字段,关联skillReview
|
||||
- **GitHub数据采集模块** (`src/lib/github.ts`): octokit封装,支持searchHotRepos搜索热门仓库、getRepoReadme获取README
|
||||
- **DeepSeek评测生成模块** (`src/lib/deepseek.ts`): OpenAI兼容接口,五维评测提示词模板,综合分自动校验
|
||||
- **自动化评测脚本** (`scripts/auto-review.mjs`): GitHub搜索→README获取→DeepSeek评测→入库全流程,每日限制8个
|
||||
- **评测API** (`/api/skills/[slug]/review`): 获取PUBLISHED状态的五维评测数据
|
||||
- **SkillReviewCard组件**: Chart.js雷达图+维度详情卡片,dynamic import(ssr:false),紫色主色调
|
||||
- **技能详情页集成**: 在标签卡片和评论之间展示五维评测雷达图
|
||||
- **发布评测脚本** (`scripts/publish-reviews.mjs`): 批量将DRAFT评测改为PUBLISHED
|
||||
- **测试脚本**: test-github.mjs(GitHub API)、test-deepseek.mjs(DeepSeek API)
|
||||
- **新依赖**: octokit, openai, chart.js, react-chartjs-2
|
||||
|
||||
### 修改
|
||||
- .env新增GITHUB_TOKEN、DEEPSEEK_API_KEY配置
|
||||
- 开发规则更新: 允许服务端脚本调用外部AI API,前端仍禁止
|
||||
- 迁移记录: 第10次迁移 add_skill_reviews
|
||||
|
||||
### 踩坑
|
||||
- Prisma 7.8需通过PrismaMariaDb适配器初始化,脚本中不能直接new PrismaClient()
|
||||
- Chart.js组件需dynamic import + ssr:false,不支持服务端渲染
|
||||
- 服务器环境SSL证书问题: 运行脚本需设置$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
|
||||
- Chart.js font.weight只接受bold/normal/bolder/lighter,不接受数字字符串如"500"
|
||||
|
||||
---
|
||||
|
||||
## v0.9.0 (2026-05-09)
|
||||
|
||||
### 重大变更
|
||||
- **移除所有外部AI API调用**: discover-tools、discover-skills、discover-news三个API不再调用DeepSeek API,改为接收前端提交的JSON数据
|
||||
- **端口迁移**: 开发端口从3100-3110迁移至8301-8310,默认端口8301
|
||||
- **五大操作指令模式重构**: 从"一键调用API"模式改为"提示词+JSON粘贴导入"模式
|
||||
|
||||
### 新增
|
||||
- AI新闻发现页面 `/admin/discover-news`:3步流程(复制提示词→粘贴JSON→查看日报),6大分类+热度评分
|
||||
- AI新闻发现API `POST /api/admin/discover-news`:接收新闻JSON数组,自动生成今日AI日报
|
||||
- AI新闻发现API `GET /api/admin/discover-news`:获取今日AI日报
|
||||
- `fetchLogoWithMethod()` 函数:返回Logo URL + 成功方法名(如"HTML Link图标"、"OG/Twitter图片"等)
|
||||
- 检测AI工具页面增加Logo抓取功能:检测时同步抓取缺失Logo,记录成功方法名统计
|
||||
- 检测AI工具页面增加Logo抓取方法统计面板:按成功次数排序展示每种方法的效果
|
||||
- 检测AI工具页面增加Logo新抓取成功列表:展示Logo预览和使用的抓取方法名
|
||||
- 导入10天100条真实AI新闻(4月30日-5月9日)
|
||||
|
||||
### 修改
|
||||
- discover-tools API: 从调用DeepSeek API改为接收 `{tools: [...], categoryId}` JSON数组
|
||||
- discover-skills API: 从调用DeepSeek API改为接收 `{skills: [...], categoryId}` JSON数组
|
||||
- discover-tools页面: 从一键发现改为4步流程(选分类→复制提示词→粘贴JSON→抓取Logo)
|
||||
- discover-skills页面: 从一键发现改为3步流程(选分类→复制提示词→粘贴JSON)
|
||||
- discover-news页面: 从一键发现改为3步流程(复制提示词→粘贴JSON→查看日报)
|
||||
- check-tools API: 增加Logo抓取功能,返回logoFetched/logoMethod/logoUrl字段,GET请求获取HTML用于Logo抓取
|
||||
- check-tools页面: 默认选中待审核工具,4步流程卡片,增加Logo抓取方法统计和新抓取成功列表
|
||||
- update-skills页面: 去掉复制提示词,保留快速更新Star
|
||||
- logo-fetcher.ts: 新增 `fetchLogoWithMethod()` 导出,每种成功方法返回中文名称
|
||||
- package.json: 端口3100→8301
|
||||
- .env: NEXTAUTH_URL端口3100→8301
|
||||
- restart.ps1: 端口扫描范围3100-3110→8301-8310
|
||||
- project_rules.md: 端口规范8301-8310,新增强制要求;五大操作指令改为提示词+JSON粘贴模式;禁止硬编码API Key;禁止调用外部AI API
|
||||
|
||||
### 删除
|
||||
- 移除3个API文件中的DeepSeek API调用逻辑(硬编码API Key、callDeepSeek函数等)
|
||||
- 移除discover-tools页面的"一键发现"按钮和DeepSeek API调用
|
||||
- 移除discover-skills页面的"一键发现"按钮和DeepSeek API调用
|
||||
- 移除discover-news页面的DeepSeek API调用
|
||||
- 清除旧的虚构AI新闻数据
|
||||
|
||||
---
|
||||
|
||||
## v0.8.0 (2026-05-05)
|
||||
|
||||
### 新增
|
||||
- 用户系统:邮箱注册/登录、GitHub OAuth登录、用户中心页面
|
||||
- 收藏功能:工具/技能收藏、收藏列表页面、乐观更新按钮
|
||||
- 浏览历史:自动记录浏览过的工具/技能
|
||||
- 评论评价系统:ReviewSection组件,支持评分和文字评论
|
||||
- LoginModal组件:登录/注册弹窗,支持模式切换
|
||||
- FavoriteButton组件:收藏按钮,乐观更新
|
||||
- CategorySidebar组件:通用分类侧边栏
|
||||
- 用户API: `/api/user/favorites`, `/api/user/history`
|
||||
- 评论API: `/api/reviews`
|
||||
- 首页API: `/api/homepage`(含嵌套分类结构)
|
||||
|
||||
### 改进
|
||||
- **UI主题重构:暗色→浅色主题**
|
||||
- 全局CSS变量从暗色切换为浅色(background: 210 20% 98%, card: 0 0% 100%等)
|
||||
- 所有页面和组件适配浅色主题(7个前台页面+12个后台页面+5个组件)
|
||||
- 颜色规范:文字-600/-700、背景-50、边框-200/60
|
||||
- 卡片样式:bg-white/60/80 + shadow-sm,hover时bg-white + shadow-md
|
||||
- 输入框:bg-muted/50 focus:bg-white focus:ring-2 focus:ring-primary/10
|
||||
- 毛玻璃效果:bg-white/80 backdrop-blur-xl
|
||||
- 渐变文字:蓝→紫→粉渐变保持科技感
|
||||
- 移除noise纹理,新增dot-grid点阵背景
|
||||
- **层级分类导航重构**
|
||||
- 首页/技能页:左侧固定一级分类导航 + 右侧二级分类标签切换
|
||||
- 每个一级类目下有"全部"标签显示该分类下所有内容
|
||||
- 左侧导航sticky跟随页面滚动
|
||||
- **安全加固**
|
||||
- 新增admin-auth.ts中间件,requireAdmin函数
|
||||
- 28个后台API端点全部添加requireAdmin中间件验证
|
||||
- 移除硬编码API密钥,改用环境变量
|
||||
- Header组件:滚动时bg-white/80 backdrop-blur-2xl,搜索框bg-muted/50
|
||||
- Logo位置修复:Header容器宽度统一为max-w-[1440px]
|
||||
### 🔧 技术改进
|
||||
- **NextAuth 类型扩展** (`src/types/next-auth.d.ts`) — Session/User/JWT 包含 level/points
|
||||
- **auth.ts 增强** — JWT/Session回调包含 level/points
|
||||
- **客户端安全架构** — level-config.ts 与 points-reward.ts 分离,避免客户端打包Node.js原生模块
|
||||
- **Header 增强** — 新增社区导航链接 + 通知铃铛 + 会员等级徽章
|
||||
- **/user 页面增强** — 积分进度条/积分明细/统计卡片
|
||||
|
||||
### 修复
|
||||
- 修复webpack缓存损坏导致的页面加载失败(清除.next目录)
|
||||
- 修复左侧导航栏sticky定位不生效(flex容器添加self-start)
|
||||
- 修复Logo被左侧导航遮挡(统一容器宽度)
|
||||
- ForumPost 新增 `isAnswer` 字段(标记最佳回答)
|
||||
- Prisma schema 日期默认值修正 `@default(now)` → `@default(now())`
|
||||
- 迁移兼容问题处理(`prisma db push` 同步)
|
||||
|
||||
### 统计数据(本次新增)
|
||||
- **新增文件**: 15个
|
||||
- **新增API端点**: 15个
|
||||
- **新增页面**: 3个
|
||||
- **新增组件**: 8个
|
||||
- **新增数据模型**: 1个(PointsHistory)
|
||||
|
||||
---
|
||||
|
||||
## v0.5.0 (2026-05-03)
|
||||
|
||||
### 新增
|
||||
- 待审核工具页面批量多选功能:全选/批量通过/批量拒绝
|
||||
- 待审核技能页面批量多选功能:全选/批量通过/批量拒绝
|
||||
- 待审核技能一键全部通过功能
|
||||
- 所有列表页面分页功能(每页20条)
|
||||
- 批量拒绝API: `/api/admin/pending/batch-reject`, `/api/admin/pending-skills/batch-reject`
|
||||
- 一键全部发布API: `/api/admin/pending-skills/publish-all`
|
||||
- AI技能自动探索API: `/api/admin/discover-skills/run`
|
||||
- 探索脚本存入系统配置,discover-skills页面展示脚本和调用说明
|
||||
- 一键自动探索按钮(服务端调用DeepSeek API)
|
||||
- Logo抓取策略改进:新增manifest.json解析、更多link/img匹配模式、图片URL验证
|
||||
- 工具库与脚本模块文档: `.trae/specs/modules/07-lib-and-scripts.md`
|
||||
|
||||
### 改进
|
||||
- Logo抓取引擎增强:6种策略按优先级,minFileSize降至50字节,timeout增至10秒
|
||||
- 待审核工具页面:新增Logo状态列、Logo筛选、抓取缺失Logo/重新抓取全部Logo按钮
|
||||
- 待审核技能页面:新增Star数展示、GitHub链接、分类标签
|
||||
- pending API和pending-skills API支持分页参数
|
||||
- 技术文档全面更新(7个模块文档+索引+开发规则+变更日志)
|
||||
|
||||
---
|
||||
|
||||
## v0.4.0 (2026-05-02)
|
||||
|
||||
### 新增
|
||||
- 系统配置页面:Logo抓取配置、发现提示词配置
|
||||
- 四个AI发现菜单:探索AI工具、检测AI工具、探索Skill技能、更新Skill技能
|
||||
- AI技能发现脚本 `scripts/discover-skills.mjs`
|
||||
- GitHub中文友好判断标准(4步标准)
|
||||
- 技能分类管理页面
|
||||
- DeepSeek V4 Pro API配置
|
||||
|
||||
### 改进
|
||||
- 配置驱动模式:提示词和Logo抓取策略存储在SystemConfig表
|
||||
- 去掉DeepSeek API配置功能,改为配置项驱动
|
||||
- 技能发现提示词优化
|
||||
|
||||
---
|
||||
|
||||
## v0.3.0 (2026-05-01)
|
||||
|
||||
### 新增
|
||||
- 技能库模块:Skill/PendingSkill数据模型、API、管理页面
|
||||
- API接口配置:ApiProvider数据模型和管理页面
|
||||
- 发现配置:DiscoveryConfig与分类管理集成
|
||||
- 公共Logo抓取工具 `src/lib/logo-fetcher.ts`
|
||||
- 服务重启脚本 `restart.ps1`
|
||||
|
||||
### 改进
|
||||
- 去除爬虫功能,改为AI发现模式
|
||||
- UI全面优化:暗色主题、毛玻璃效果、动画
|
||||
- 端口从3000改为3100
|
||||
|
||||
---
|
||||
|
||||
## v0.2.0 (2026-04-30)
|
||||
|
||||
### 新增
|
||||
- 后台管理页面:工具管理、分类管理、待审核工具
|
||||
- NextAuth认证系统
|
||||
- Prisma ORM + MySQL数据库
|
||||
- AI智能发现新工具功能(DeepSeek API)
|
||||
- 批量导入工具脚本
|
||||
|
||||
---
|
||||
|
||||
## v0.1.0 (2026-04-28)
|
||||
|
||||
### 新增
|
||||
- Next.js 14项目初始化
|
||||
- Tailwind CSS + shadcn/ui配置
|
||||
- 前台页面:首页、工具列表、工具详情、分类页
|
||||
- Header/Footer布局组件
|
||||
## 2026-05-24 全面技术文档生成
|
||||
(详见历史 CHANGELOG 记录)
|
||||
@@ -127,11 +127,30 @@
|
||||
- GITHUB_TOKEN: GitHub Personal Access Token(可选,提升API限流从60→5000次/小时)
|
||||
- DEEPSEEK_API_KEY: DeepSeek API Key(用于技能评测生成脚本、AI日报整理)
|
||||
|
||||
## 定时任务(Crontab)
|
||||
- **AI日报生成**: 每天 7:30 — `scripts/daily-news.mjs`(搜索真实新闻 + DeepSeek整理格式)
|
||||
- **技能自动发现**: 每天 2:00 — `scripts/daily-discover.mjs`(GitHub搜索 + DeepSeek评测 + 入库)
|
||||
- 运行脚本: `/home/ubuntu/zhuiguang-ai/scripts/cron-daily-news.sh` / `cron-daily-discover.sh`
|
||||
- 日志目录: `/home/ubuntu/zhuiguang-ai/logs/`
|
||||
## 定时任务调度系统
|
||||
- **后台管理**: `/admin/tasks`(任务中心)、`/admin/tasks/logs`(执行日志)、`/admin/tasks/[taskKey]`(单任务详情+统计)
|
||||
- **数据模型**: TaskConfig(任务配置,含enabled/cronExpr/config)、TaskLog(执行历史,含status/duration/result/error)
|
||||
- **种子数据**: `scripts/seed-task-configs.mjs` 初始化6个任务配置
|
||||
- **手动触发**: `/admin/tasks` 页支持每个任务运行,也可通过 POST `/api/admin/tasks/run` 触发
|
||||
- **API**:
|
||||
- `GET/PUT /api/admin/tasks/configs` — 任务配置查询/更新
|
||||
- `GET /api/admin/tasks/logs` — 任务执行日志(分页+按taskKey筛选)
|
||||
- `POST /api/admin/tasks/run` — 手动触发任务执行
|
||||
|
||||
### 定时任务(Crontab)
|
||||
所有6个定时任务全部经过TaskLog记录:
|
||||
|
||||
| 时间 | 任务 | 脚本 | TaskKey | 说明 |
|
||||
|------|------|------|---------|------|
|
||||
| 01:00 | Task5 更新星值 | `scripts/task5-update-stars.mjs` | task5-update-stars | 更新所有GitHub技能Stars数+日/周/月变化 |
|
||||
| 03:00 | Task3 工具巡检 | `scripts/task3-check-tools.mjs` | task3-check-tools | 检查网站/Lo4go可访问性+自动发布合格待审核工具 |
|
||||
| 04:00 | Task6 评测热门 | `scripts/task6-review-hot.mjs` | task6-review-hot | 评测2个最热未评测GitHub技能(五维评测) |
|
||||
| 05:00 | Task4 发现技能 | `scripts/daily-discover.mjs` | task4-discover-skills | GitHub搜索≥1000 stars项目→DeepSeek预评测→入库PendingSkill |
|
||||
| 06:00 | Task1 发现工具 | `scripts/task1-discover-tools.mjs` | task1-discover-tools | 36kr/IT之家/开源中国RSS→DeepSeek提取工具→入库PendingTool |
|
||||
| 07:30 | AI日报 | `scripts/daily-news.mjs` | daily-news | 多源搜索真实新闻+DeepSeek整理格式→发布日报 |
|
||||
|
||||
- Crontab 位于服务器: `crontab -l`(ubuntu用户)
|
||||
- 日志目录: `/home/ubuntu/zhuiguang-ai/logs/`(task1.log ~ task6.log)
|
||||
|
||||
## AI日报新闻源
|
||||
- **36kr** RSS (https://36kr.com/feed) — 国内科技资讯
|
||||
|
||||
+35
-25
@@ -1,7 +1,7 @@
|
||||
# 追光AI - 模块文档索引
|
||||
|
||||
## 项目概述
|
||||
追光AI是一个AI工具与开源技能目录网站,支持提示词驱动的工具/技能发现、审核管理和前台展示。
|
||||
追光AI是一个AI工具与开源技能目录网站,支持提示词驱动的工具/技能发现、审核管理和前台展示,集成五维评测系统、任务调度、权限体系和社区互动功能。
|
||||
|
||||
## 技术栈
|
||||
|
||||
@@ -12,48 +12,54 @@
|
||||
| 样式 | Tailwind CSS + shadcn/ui | 3.x |
|
||||
| 数据库 | MySQL (阿里云RDS) + Prisma | 7.8 |
|
||||
| 认证 | NextAuth.js | v4 |
|
||||
| AI | DeepSeek API (技能评测生成) | deepseek-v4-pro |
|
||||
| AI | DeepSeek API (deepseek-v4-pro) | 服务端脚本调用 |
|
||||
| 图表 | Chart.js + react-chartjs-2 | 4.x |
|
||||
| 部署 | Node.js | 18+ |
|
||||
| GitHub | Octokit | 5.x |
|
||||
| 验证 | Zod | 4.x |
|
||||
| 部署 | Node.js + PM2 | 18+ |
|
||||
| 端口 | 8301-8310 | 默认8301 |
|
||||
|
||||
## 项目结构
|
||||
```
|
||||
zhuiguang-ai/
|
||||
├── prisma/ # 数据库Schema + 迁移 + 种子
|
||||
├── public/ # 静态资源 (logo.png, logos/)
|
||||
├── scripts/ # 独立脚本 (discover-skills, import-tools)
|
||||
├── prisma/ # 数据库Schema + 迁移 + 种子
|
||||
├── public/ # 静态资源 (logo.png, logos/)
|
||||
├── scripts/ # 独立脚本 (6个定时任务 + 多个工具脚本)
|
||||
├── src/
|
||||
│ ├── app/
|
||||
│ │ ├── (admin)/admin/ # 后台页面 (15个页面)
|
||||
│ │ ├── api/ # API路由 (36+个端点)
|
||||
│ │ ├── (admin)/admin/ # 后台页面 (18个页面 + 任务调度3个子页)
|
||||
│ │ ├── api/ # API路由 (50+个端点)
|
||||
│ │ ├── categories/ # 前台分类页
|
||||
│ │ ├── reviews/ # 前台评测列表+榜单
|
||||
│ │ ├── skills/ # 前台技能页
|
||||
│ │ ├── tools/ # 前台工具页
|
||||
│ │ ├── login/ # 用户登录页
|
||||
│ │ ├── user/ # 用户中心(个人资料/收藏)
|
||||
│ │ ├── daily/ # AI日报页
|
||||
│ │ ├── user/ # 用户中心(个人资料/收藏/收藏夹)
|
||||
│ │ ├── globals.css # 全局样式
|
||||
│ │ ├── layout.tsx # 前台布局
|
||||
│ │ └── page.tsx # 首页
|
||||
│ ├── components/ # 组件 (Header, Footer, UI, Common)
|
||||
│ ├── lib/ # 工具库 (prisma, auth, admin-auth, github, deepseek, logo-fetcher, logo-storage, utils)
|
||||
│ └── middleware.ts # 路由保护
|
||||
├── .env # 环境变量
|
||||
├── restart.ps1 # 服务重启脚本(端口8301-8310)
|
||||
└── package.json # 依赖配置
|
||||
│ ├── components/ # 组件 (Header, Footer, UI, Common)
|
||||
│ ├── lib/ # 工具库 (prisma, auth, admin-auth, github, deepseek, logo-fetcher, logo-storage, utils)
|
||||
│ └── middleware.ts # 路由保护
|
||||
├── .env # 环境变量
|
||||
├── restart.ps1 # 服务重启脚本(端口8301-8310)
|
||||
└── package.json # 依赖配置
|
||||
```
|
||||
|
||||
## 模块文档
|
||||
|
||||
| 序号 | 模块 | 文档 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 01 | 数据库 | [01-database.md](./modules/01-database.md) | 数据模型、枚举、索引、迁移历史 |
|
||||
| 02 | API | [02-api.md](./modules/02-api.md) | 前台/后台API端点、SystemConfig配置键 |
|
||||
| 01 | 数据库 | [01-database.md](./modules/01-database.md) | 26张数据模型、8个枚举、完整索引、迁移历史 |
|
||||
| 02 | API | [02-api.md](./modules/02-api.md) | 前台/后台/用户API端点、SystemConfig配置键 |
|
||||
| 03 | 页面 | [03-pages.md](./modules/03-pages.md) | 前台/后台页面路由、布局、功能说明 |
|
||||
| 04 | 组件与样式 | [04-components-and-styles.md](./modules/04-components-and-styles.md) | UI组件、样式系统、设计规范 |
|
||||
| 05 | AI发现 | [05-ai-discovery.md](./modules/05-ai-discovery.md) | 提示词驱动发现流程、Logo抓取引擎、新闻发现 |
|
||||
| 06 | 认证 | [06-auth.md](./modules/06-auth.md) | NextAuth配置、路由保护、登录流程 |
|
||||
| 07 | 工具库与脚本 | [07-lib-and-scripts.md](./modules/07-lib-and-scripts.md) | 工具函数、独立脚本、运维脚本 |
|
||||
| 05 | AI发现 | [05-ai-discovery.md](./modules/05-ai-discovery.md) | 提示词驱动发现流程、Logo抓取引擎、定时任务、评测管线 |
|
||||
| 06 | 认证 | [06-auth.md](./modules/06-auth.md) | NextAuth配置、路由保护、权限体系、登录流程 |
|
||||
| 07 | 工具库与脚本 | [07-lib-and-scripts.md](./modules/07-lib-and-scripts.md) | 工具函数、定时任务脚本、运维脚本 |
|
||||
| 08 | 社区功能 | [08-community.md](./modules/08-community.md) | 评论系统、收藏、浏览历史、收藏夹、通知、论坛 |
|
||||
| 09 | 运维与部署 | [09-devops.md](./modules/09-devops.md) | 服务器配置、Nginx、Crontab、部署流程、踩坑记录 |
|
||||
|
||||
## 环境变量
|
||||
```
|
||||
@@ -70,7 +76,7 @@ DEEPSEEK_API_KEY=<required-for-review>
|
||||
→ PendingTool / PendingSkill (待审核)
|
||||
→ 管理员审核(编辑/发布/拒绝/批量操作)
|
||||
→ Tool / Skill (已发布)
|
||||
→ 前台展示(分类浏览/搜索/详情)
|
||||
→ 前台展示(分类浏览/搜索/详情/评测/评论)
|
||||
```
|
||||
|
||||
## 关键特性
|
||||
@@ -79,12 +85,16 @@ DEEPSEEK_API_KEY=<required-for-review>
|
||||
- **检测+Logo联动**: 检测AI工具时同步抓取缺失Logo,记录每种抓取方法的成功次数统计
|
||||
- **双轨内容**: 工具(Tool)面向商业AI产品,技能(Skill)面向GitHub开源项目
|
||||
- **批量操作**: 批量导入、批量发布、批量拒绝、一键全部通过
|
||||
- **GitHub Star同步**: 通过GitHub API定期更新技能Star数
|
||||
- **AI新闻发现**: 提示词驱动发现AI新闻,按日生成日报,6大分类+热度评分
|
||||
- **GitHub Star同步**: 通过GitHub API定期更新技能Star数,维护90天历史
|
||||
- **五维评测系统**: GitHub数据采集 + DeepSeek AI评测 + 雷达图展示,5维度(capability/devExp/costLicense/community/performance)评分
|
||||
- **评测榜单**: 前台/reviews页面展示评测分榜TOP10 + Stars涨幅榜TOP10侧边栏
|
||||
- **任务调度系统**: 6个定时任务(Task1-6)+AI日报,统一TaskConfig配置+TaskLog执行历史+后台可视化管理+手动触发
|
||||
- **权限体系**: 53个精细化权限点,角色管理,细粒度权限控制
|
||||
- **社区互动**: 评论/回复、收藏、浏览历史、收藏夹、通知系统、论坛板块
|
||||
- **分页**: 所有列表页面支持分页(每页20条)
|
||||
- **浅色主题**: 科技感浅色设计系统,毛玻璃效果+渐变文字+精致阴影
|
||||
- **层级分类**: 一级分类+二级分类,左侧导航+标签切换
|
||||
- **用户系统**: 邮箱注册/登录、收藏功能、浏览历史
|
||||
- **安全加固**: 28个后台API全部添加requireAdmin中间件验证
|
||||
- **用户系统**: 邮箱注册/登录、GitHub OAuth、收藏功能、浏览历史
|
||||
- **安全加固**: 后台API全部添加requireAdmin中间件验证,路由层+中间件双重防御
|
||||
- **端口锁定**: 8301-8310区间,禁止使用其他端口
|
||||
- **频率限制**: 登录尝试限制、IP请求限制
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- Prisma 7.8 + @prisma/adapter-mariadb
|
||||
- MySQL (阿里云RDS)
|
||||
- 连接字符串: `mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai`
|
||||
- Prisma单例模式防止热重载多实例
|
||||
|
||||
## 数据模型
|
||||
|
||||
@@ -11,126 +12,511 @@
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(100) | 分类名称 |
|
||||
| slug | String @unique @db.VarChar(100) | URL标识 |
|
||||
| icon | String? | 图标 |
|
||||
| parentId | Int? | 父分类ID(自引用) |
|
||||
| sortOrder | Int @default(0) | 排序权重 |
|
||||
| createdAt | DateTime | 创建时间 |
|
||||
| updatedAt | DateTime | 更新时间 |
|
||||
| name | String @db.VarChar(50) | 分类名称 |
|
||||
| slug | String @unique @db.VarChar(50) | URL标识 |
|
||||
| icon | String? @db.VarChar(100) | 图标 |
|
||||
| parentId | Int? @map("parent_id") | 父分类ID(自引用) |
|
||||
| sortOrder | Int @default(0) @map("sort_order") | 排序权重 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: tools (Tool[]), pendingTools (PendingTool[]), parent/children (自引用层级)
|
||||
|
||||
### SkillCategory (技能分类)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(100) | 分类名称 |
|
||||
| slug | String @unique @db.VarChar(100) | URL标识 |
|
||||
| icon | String? | 图标 |
|
||||
| parentId | Int? | 父分类ID(自引用) |
|
||||
| sortOrder | Int @default(0) | 排序权重 |
|
||||
| createdAt | DateTime | 创建时间 |
|
||||
| updatedAt | DateTime | 更新时间 |
|
||||
| name | String @db.VarChar(50) | 分类名称 |
|
||||
| slug | String @unique @db.VarChar(50) | URL标识 |
|
||||
| icon | String? @db.VarChar(100) | 图标 |
|
||||
| parentId | Int? @map("parent_id") | 父分类ID(自引用) |
|
||||
| sortOrder | Int @default(0) @map("sort_order") | 排序权重 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: skills (Skill[]), pendingSkills (PendingSkill[]), parent/children (自引用层级)
|
||||
|
||||
### Tool (已发布工具)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id | 主键 |
|
||||
| name | String | 工具名称 |
|
||||
| slug | String @unique | URL标识 |
|
||||
| categoryId | Int | 分类ID(必填) |
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(100) | 工具名称 |
|
||||
| slug | String @unique @db.VarChar(100) | URL标识 |
|
||||
| categoryId | Int @map("category_id") | 分类ID |
|
||||
| description | String @db.Text | 简介 |
|
||||
| logoUrl | String? | Logo地址 |
|
||||
| websiteUrl | String | 官网地址 |
|
||||
| pricingModel | PricingModel | 定价模型(free/freemium/paid/subscription) |
|
||||
| pricingDetail | String? | 定价详情 |
|
||||
| features | Json? | 功能特性数组 |
|
||||
| tags | Json? | 标签数组 |
|
||||
| viewCount | Int @default(0) | 浏览次数 |
|
||||
| logoUrl | String? @map("logo_url") @db.VarChar(255) | Logo地址 |
|
||||
| websiteUrl | String @map("website_url") @db.VarChar(255) | 官网地址 |
|
||||
| pricingModel | PricingModel @default(freemium) | 定价模型 |
|
||||
| pricingDetail | String? @map("pricing_detail") @db.VarChar(200) | 定价详情 |
|
||||
| features | Json? | 功能特性(JSON) |
|
||||
| tags | Json? | 标签数组(JSON) |
|
||||
| viewCount | Int @default(0) @map("view_count") | 浏览次数 |
|
||||
| commentCount | Int @default(0) @map("comment_count") | 评论数 |
|
||||
| avgRating | Float @default(0) @map("avg_rating") | 平均评分 |
|
||||
| status | Status @default(draft) | 状态(draft/published) |
|
||||
| createdAt/updatedAt | DateTime | 时间戳 |
|
||||
| lastCheckedAt | DateTime? @map("last_checked_at") | 最后巡检时间 |
|
||||
| websiteOk | Boolean @default(true) @map("website_ok") | 网站可访问 |
|
||||
| logoOk | Boolean @default(true) @map("logo_ok") | Logo有效 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: category, favorites, browsingHistory, reviews, collectionItems, comments
|
||||
|
||||
### PendingTool (待审核工具)
|
||||
与Tool类似,但categoryId/description/websiteUrl等可为空,额外有sourceUrl和status(pending/approved/rejected)。
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(100) | 工具名称 |
|
||||
| slug | String? @db.VarChar(100) | URL标识 |
|
||||
| categoryId | Int? @map("category_id") | 分类ID |
|
||||
| description | String? @db.Text | 简介 |
|
||||
| logoUrl | String? @map("logo_url") @db.VarChar(255) | Logo地址 |
|
||||
| websiteUrl | String? @map("website_url") @db.VarChar(255) | 官网地址 |
|
||||
| pricingModel | PricingModel? @default(freemium) | 定价模型 |
|
||||
| pricingDetail | String? @map("pricing_detail") @db.VarChar(200) | 定价详情 |
|
||||
| features | Json? | 功能特性 |
|
||||
| tags | Json? | 标签数组 |
|
||||
| sourceUrl | String? @map("source_url") @db.VarChar(255) | 来源地址 |
|
||||
| status | PendingStatus @default(pending) | 状态(pending/approved/rejected) |
|
||||
| checkWebsiteOk | Boolean? @map("check_website_ok") | 网站可访问检查结果 |
|
||||
| checkLogoOk | Boolean? @map("check_logo_ok") | Logo检查结果 |
|
||||
| checkDescOk | Boolean? @map("check_desc_ok") | 描述检查结果 |
|
||||
| checkCategoryOk | Boolean? @map("check_category_ok") | 分类检查结果 |
|
||||
| checkDetail | Json? @map("check_detail") | 检查详情(JSON) |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: category
|
||||
|
||||
### Skill (已发布技能)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id | 主键 |
|
||||
| name | String | 技能名称 |
|
||||
| slug | String @unique | URL标识 |
|
||||
| categoryId | Int | 分类ID(必填) |
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(100) | 技能名称 |
|
||||
| slug | String @unique @db.VarChar(100) | URL标识 |
|
||||
| categoryId | Int @map("category_id") | 分类ID |
|
||||
| description | String @db.Text | 简介 |
|
||||
| logoUrl | String? | Logo地址 |
|
||||
| sourceUrl | String | GitHub仓库地址 |
|
||||
| sourceType | String @default("gitee") | 来源类型 |
|
||||
| rating | Float @default(0) | 综合评分 |
|
||||
| features | Json? | 功能特性(含forks/language/license/topics) |
|
||||
| logoUrl | String? @map("logo_url") @db.VarChar(255) | Logo地址 |
|
||||
| sourceUrl | String @map("source_url") @db.VarChar(255) | 源码地址(GitHub) |
|
||||
| sourceType | String @default("gitee") @db.VarChar(20) | 来源类型 |
|
||||
| rating | Float @default(0) @db.Float | 综合评分 |
|
||||
| features | Json? | 功能特性(forks/language/license/topics) |
|
||||
| tags | Json? | 标签数组 |
|
||||
| viewCount | Int @default(0) | 浏览次数 |
|
||||
| status | Status | 状态 |
|
||||
| lastReviewedAt | DateTime? | 最近评测时间 |
|
||||
| githubStarsHistory | Json? | Star历史数据 |
|
||||
| viewCount | Int @default(0) @map("view_count") | 浏览次数 |
|
||||
| status | Status @default(draft) | 状态 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
| lastReviewedAt | DateTime? @map("last_reviewed_at") | 最近评测时间 |
|
||||
| githubStarsHistory | Json? @map("github_stars_history") | Star历史数据(90天) |
|
||||
| githubStars | Int @default(0) @map("github_stars") | 当前GitHub Stars |
|
||||
| starsChangeDay | Int @default(0) @map("stars_change_day") | 日Star变化 |
|
||||
| starsChangeWeek | Int @default(0) @map("stars_change_week") | 周Star变化 |
|
||||
| starsChangeMonth | Int @default(0) @map("stars_change_month") | 月Star变化 |
|
||||
| commentCount | Int @default(0) @map("comment_count") | 评论数 |
|
||||
| avgRating | Float @default(0) @map("avg_rating") | 平均评分 |
|
||||
|
||||
**关系**: category, favorites, browsingHistory, reviews, collectionItems, skillReview, comments
|
||||
|
||||
### PendingSkill (待审核技能)
|
||||
与Skill类似,但多个字段可为空。
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(100) | 技能名称 |
|
||||
| slug | String? @db.VarChar(100) | URL标识 |
|
||||
| categoryId | Int? @map("category_id") | 分类ID |
|
||||
| description | String? @db.Text | 简介 |
|
||||
| logoUrl | String? @map("logo_url") @db.VarChar(255) | Logo地址 |
|
||||
| sourceUrl | String? @map("source_url") @db.VarChar(255) | 源码地址 |
|
||||
| sourceType | String? @map("source_type") @db.VarChar(20) | 来源类型 |
|
||||
| rating | Float @default(0) @db.Float | 综合评分 |
|
||||
| features | Json? | 功能特性 |
|
||||
| tags | Json? | 标签数组 |
|
||||
| status | PendingStatus @default(pending) | 状态 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: category
|
||||
|
||||
### User (用户)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| email | String @unique @db.VarChar(255) | 邮箱 |
|
||||
| passwordHash | String? @db.VarChar(255) | 密码哈希(bcrypt) |
|
||||
| name | String? @db.VarChar(100) | 昵称 |
|
||||
| avatarUrl | String? | 头像地址 |
|
||||
| oauthProvider | String? @db.VarChar(50) | OAuth提供商(github) |
|
||||
| oauthId | String? @unique @db.VarChar(255) | OAuth外部ID |
|
||||
| role | String @default("user") @db.VarChar(20) | 角色字符串(向后兼容) |
|
||||
| roleId | Int? @map("role_id") | 角色ID(关联Role表) |
|
||||
| points | Int @default(0) | 积分 |
|
||||
| level | UserLevel @default(BRONZE) | 用户等级 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: assignedRole, favorites, browsingHistory, reviews, collections, comments, commentLikes, notifications, forumTopics, forumPosts
|
||||
|
||||
### Role (角色)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(50) | 角色名称 |
|
||||
| slug | String @unique @db.VarChar(50) | 角色标识 |
|
||||
| isSystem | Boolean @default(false) @map("is_system") | 是否系统角色(受保护) |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: permissions (RolePermission[]), users (User[])
|
||||
|
||||
### Permission (权限点)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| groupName | String @map("group_name") @db.VarChar(50) | 权限分组 |
|
||||
| name | String @db.VarChar(50) | 权限名称 |
|
||||
| key | String @unique @db.VarChar(80) | 权限键(唯一) |
|
||||
| sortOrder | Int @default(0) @map("sort_order") | 排序权重 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: rolePermissions
|
||||
|
||||
### RolePermission (角色-权限关联)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| roleId | Int @map("role_id") | 角色ID(联合主键) |
|
||||
| permissionId | Int @map("permission_id") | 权限ID(联合主键) |
|
||||
|
||||
**关系**: role, permission (onDelete: Cascade)
|
||||
|
||||
### SystemConfig (系统配置)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id | 主键 |
|
||||
| key | String @unique | 配置键 |
|
||||
| value | Json | 配置值(JSON) |
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| key | String @unique @db.VarChar(50) | 配置键 |
|
||||
| value | Json | 配置值(JSON) |
|
||||
|
||||
### SkillReview (技能评测)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| skillId | Int @unique | 关联Skill(一对一) |
|
||||
| skillId | Int @unique @map("skill_id") | 关联Skill(一对一) |
|
||||
| capability | Float | 场景与能力评分(1-5) |
|
||||
| devExp | Float | 开发体验评分(1-5) |
|
||||
| costLicense | Float | 成本与许可评分(1-5) |
|
||||
| devExp | Float @map("dev_exp") | 开发体验评分(1-5) |
|
||||
| costLicense | Float @map("cost_license") | 成本与许可评分(1-5) |
|
||||
| community | Float | 社区健康评分(1-5) |
|
||||
| performance | Float | 性能稳定评分(1-5) |
|
||||
| overall | Float | 综合评分(五维均值) |
|
||||
| reviews | Json | 完整评测数据(含各维度summary/detail) |
|
||||
| longArticle | String? @db.Text | 长文评测 |
|
||||
| videoScript | String? @db.Text | 视频脚本 |
|
||||
| socialCards | Json? | 社交卡片数据 |
|
||||
| overall | Float | 综合评分(五维均值) |
|
||||
| reviews | Json | 完整评测数据(含各维度summary/detail) |
|
||||
| longArticle | String? @map("long_article") @db.Text | 长文评测 |
|
||||
| videoScript | String? @map("video_script") @db.Text | 视频脚本 |
|
||||
| socialCards | Json? @map("social_cards") | 社交卡片数据 |
|
||||
| status | ReviewStatus @default(DRAFT) | 评测状态 |
|
||||
| reviewedAt | DateTime @updatedAt | 评测时间 |
|
||||
| createdAt | DateTime | 创建时间 |
|
||||
| reviewedAt | DateTime @updatedAt @map("reviewed_at") | 评测时间 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: skill (一对一)
|
||||
|
||||
### ReviewGenerationLog (评测生成日志)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| skillId | Int | 关联Skill ID |
|
||||
| skillId | Int @map("skill_id") | 关联Skill |
|
||||
| status | String @db.VarChar(20) | SUCCESS/FAILED |
|
||||
| prompt | String @db.Text | 生成提示词 |
|
||||
| response | String? @db.Text | API响应内容 |
|
||||
| response | String? @db.Text | API响应 |
|
||||
| error | String? @db.Text | 错误信息 |
|
||||
| createdAt | DateTime | 创建时间 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
### TaskConfig (任务配置)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| taskKey | String @unique @map("task_key") @db.VarChar(50) | 任务键 |
|
||||
| taskName | String @map("task_name") @db.VarChar(100) | 任务名称 |
|
||||
| description | String? @db.VarChar(255) | 任务描述 |
|
||||
| enabled | Boolean @default(true) | 是否启用 |
|
||||
| cronExpr | String? @map("cron_expr") @db.VarChar(50) | Cron表达式 |
|
||||
| config | Json? | 任务配置(JSON) |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
### TaskLog (任务执行日志)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| taskKey | String @map("task_key") @db.VarChar(50) | 任务键 |
|
||||
| taskName | String @map("task_name") @db.VarChar(100) | 任务名称 |
|
||||
| status | String @db.VarChar(20) | 执行状态(completed/failed) |
|
||||
| startedAt | DateTime @map("started_at") | 开始时间 |
|
||||
| finishedAt | DateTime? @map("finished_at") | 结束时间 |
|
||||
| duration | Int? | 执行时长(毫秒) |
|
||||
| result | Json? | 执行结果(JSON) |
|
||||
| error | String? @db.Text | 错误信息 |
|
||||
| triggerBy | String @default("cron") @map("trigger_by") @db.VarChar(20) | 触发方式 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
### Favorite (收藏)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| toolId | Int? @map("tool_id") | 工具ID |
|
||||
| skillId | Int? @map("skill_id") | 技能ID |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 收藏时间 |
|
||||
|
||||
**关系**: user, tool, skill
|
||||
|
||||
**唯一约束**: [userId, toolId], [userId, skillId]
|
||||
|
||||
### BrowsingHistory (浏览历史)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| toolId | Int? @map("tool_id") | 工具ID |
|
||||
| skillId | Int? @map("skill_id") | 技能ID |
|
||||
| viewedAt | DateTime @default(now()) @updatedAt @map("viewed_at") | 浏览时间 |
|
||||
|
||||
**关系**: user, tool, skill
|
||||
|
||||
### Review (评论)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| toolId | Int? @map("tool_id") | 工具ID |
|
||||
| skillId | Int? @map("skill_id") | 技能ID |
|
||||
| rating | Int? | 评分(1-5) |
|
||||
| comment | String @db.Text | 评论内容 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: user, tool, skill
|
||||
|
||||
### Collection (收藏夹)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| name | String @db.VarChar(50) | 收藏夹名称 |
|
||||
| description | String? @db.Text | 描述 |
|
||||
| sortOrder | Int @default(0) @map("sort_order") | 排序 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: user, items
|
||||
|
||||
### CollectionItem (收藏夹项目)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| collectionId | Int @map("collection_id") | 收藏夹ID |
|
||||
| toolId | Int? @map("tool_id") | 工具ID |
|
||||
| skillId | Int? @map("skill_id") | 技能ID |
|
||||
| addedAt | DateTime @default(now()) @map("added_at") | 添加时间 |
|
||||
|
||||
**关系**: collection, tool, skill
|
||||
|
||||
### DailyReport (AI日报)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| date | DateTime @unique @db.Date | 日期(唯一) |
|
||||
| title | String @db.VarChar(200) | 标题 |
|
||||
| summary | String? @db.Text | 摘要 |
|
||||
| hotCount | Int @default(0) @map("hot_count") | 热门条目数 |
|
||||
| coverUrl | String? @map("cover_url") @db.VarChar(255) | 封面图 |
|
||||
| status | Status @default(draft) | 状态 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: items
|
||||
|
||||
### DailyReportItem (日报条目)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| reportId | Int @map("report_id") | 日报ID |
|
||||
| sortOrder | Int @default(0) @map("sort_order") | 排序 |
|
||||
| category | String @default("tech") @db.VarChar(20) | 分类 |
|
||||
| title | String @db.VarChar(200) | 标题 |
|
||||
| summary | String? @db.Text | 摘要 |
|
||||
| detail | String? @db.Text | 详情 |
|
||||
| sourceUrl | String? @map("source_url") @db.VarChar(500) | 来源链接 |
|
||||
| imageUrl | String? @map("image_url") @db.VarChar(255) | 图片地址 |
|
||||
| hotScore | Int @default(0) @map("hot_score") | 热度评分 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: report (onDelete: Cascade)
|
||||
|
||||
### Comment (评论/回复)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| toolId | Int? @map("tool_id") | 工具ID |
|
||||
| skillId | Int? @map("skill_id") | 技能ID |
|
||||
| parentId | Int? @map("parent_id") | 父评论ID(回复) |
|
||||
| content | String @db.Text | 评论内容 |
|
||||
| rating | Int? | 评分(1-5) |
|
||||
| likeCount | Int @default(0) @map("like_count") | 点赞数 |
|
||||
| isPinned | Boolean @default(false) @map("is_pinned") | 是否置顶 |
|
||||
| status | CommentStatus @default(ACTIVE) | 状态 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: user, tool, skill, parent/replies (自引用), likes
|
||||
|
||||
### CommentLike (评论点赞)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| commentId | Int @map("comment_id") | 评论ID |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: comment, user (onDelete: Cascade)
|
||||
|
||||
**唯一约束**: [commentId, userId]
|
||||
|
||||
### Notification (通知)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| type | NotifType | 通知类型 |
|
||||
| title | String @db.VarChar(100) | 标题 |
|
||||
| content | String? @db.VarChar(255) | 内容 |
|
||||
| link | String? @db.VarChar(255) | 跳转链接 |
|
||||
| isRead | Boolean @default(false) @map("is_read") | 是否已读 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: user
|
||||
|
||||
### ForumCategory (论坛板块)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| name | String @db.VarChar(30) | 板块名称 |
|
||||
| slug | String @unique @db.VarChar(30) | URL标识 |
|
||||
| description | String? @db.VarChar(100) | 描述 |
|
||||
| icon | String? @db.VarChar(30) | 图标 |
|
||||
| sortOrder | Int @default(0) @map("sort_order") | 排序 |
|
||||
| topicCount | Int @default(0) @map("topic_count") | 话题数 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: topics
|
||||
|
||||
### ForumTopic (论坛话题)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| categoryId | Int @map("category_id") | 板块ID |
|
||||
| userId | Int @map("user_id") | 作者ID |
|
||||
| title | String @db.VarChar(100) | 标题 |
|
||||
| slug | String @unique @db.VarChar(120) | URL标识 |
|
||||
| content | String @db.Text | 内容 |
|
||||
| isPinned | Boolean @default(false) @map("is_pinned") | 是否置顶 |
|
||||
| isLocked | Boolean @default(false) @map("is_locked") | 是否锁定 |
|
||||
| viewCount | Int @default(0) @map("view_count") | 浏览数 |
|
||||
| replyCount | Int @default(0) @map("reply_count") | 回复数 |
|
||||
| lastReplyAt | DateTime? @map("last_reply_at") | 最后回复时间 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: category, user, posts
|
||||
|
||||
### ForumPost (论坛回复)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| topicId | Int @map("topic_id") | 话题ID |
|
||||
| userId | Int @map("user_id") | 作者ID |
|
||||
| content | String @db.Text | 回复内容 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: topic, user
|
||||
|
||||
## 枚举
|
||||
- `PricingModel`: free, freemium, paid, subscription
|
||||
- `Status`: draft, published
|
||||
- `PendingStatus`: pending, approved, rejected
|
||||
- `ReviewStatus`: DRAFT, PUBLISHED, REJECTED, OUTDATED
|
||||
|
||||
### PricingModel (定价模型)
|
||||
- `free` — 免费
|
||||
- `freemium` — 免费增值
|
||||
- `paid` — 付费
|
||||
- `subscription` — 订阅制
|
||||
|
||||
### Status (状态)
|
||||
- `draft` — 草稿
|
||||
- `published` — 已发布
|
||||
|
||||
### PendingStatus (待审核状态)
|
||||
- `pending` — 待审核
|
||||
- `approved` — 已通过
|
||||
- `rejected` — 已拒绝
|
||||
|
||||
### ReviewStatus (评测状态)
|
||||
- `DRAFT` — 草稿
|
||||
- `PUBLISHED` — 已发布
|
||||
- `REJECTED` — 已拒绝
|
||||
- `OUTDATED` — 已过期
|
||||
|
||||
### UserLevel (用户等级)
|
||||
- `BRONZE` — 青铜
|
||||
- `SILVER` — 白银
|
||||
- `GOLD` — 黄金
|
||||
- `PLATINUM` — 铂金
|
||||
|
||||
### CommentStatus (评论状态)
|
||||
- `ACTIVE` — 活跃
|
||||
- `HIDDEN` — 隐藏
|
||||
- `DELETED` — 已删除
|
||||
|
||||
### NotifType (通知类型)
|
||||
- `COMMENT_REPLY` — 评论回复
|
||||
- `COMMENT_LIKE` — 评论点赞
|
||||
- `TOPIC_REPLY` — 话题回复
|
||||
- `SYSTEM` — 系统通知
|
||||
|
||||
## 索引
|
||||
- Tool: categoryId+status联合索引, name+description全文索引
|
||||
- Skill: categoryId+status联合索引
|
||||
- SkillReview: skillId索引(唯一), overall索引
|
||||
- ReviewGenerationLog: skillId索引
|
||||
|
||||
| 模型 | 索引 | 类型 |
|
||||
|------|------|------|
|
||||
| Tool | [categoryId, status] | 联合索引 |
|
||||
| Tool | [name, description] | 全文索引 |
|
||||
| Skill | [categoryId, status] | 联合索引 |
|
||||
| SkillReview | [skillId] | 唯一索引 |
|
||||
| SkillReview | [overall] | 普通索引 |
|
||||
| ReviewGenerationLog | [skillId] | 普通索引 |
|
||||
| TaskLog | [taskKey, startedAt] | 联合索引 |
|
||||
| TaskConfig | [taskKey] | 唯一索引 |
|
||||
| Favorite | [userId] | 普通索引 |
|
||||
| BrowsingHistory | [userId, viewedAt] | 联合索引 |
|
||||
| Collection | [userId] | 普通索引 |
|
||||
| DailyReport | [date] | 唯一索引 |
|
||||
| DailyReport | [status] | 普通索引 |
|
||||
| DailyReportItem | [reportId, sortOrder] | 联合索引 |
|
||||
| Comment | [toolId, createdAt] | 联合索引 |
|
||||
| Comment | [skillId, createdAt] | 联合索引 |
|
||||
| Comment | [userId] | 普通索引 |
|
||||
| Notification | [userId, isRead, createdAt] | 联合索引 |
|
||||
| ForumTopic | [categoryId, lastReplyAt] | 联合索引 |
|
||||
| ForumTopic | [userId] | 普通索引 |
|
||||
| ForumTopic | [title] | 全文索引 |
|
||||
| ForumPost | [topicId, createdAt] | 联合索引 |
|
||||
| Permission | [groupName, sortOrder] | 联合索引 |
|
||||
| User | [oauthProvider, oauthId] | 联合唯一 |
|
||||
|
||||
## 迁移历史
|
||||
1. init - 初始化
|
||||
2. remove_scraped_at - 移除scrapedAt字段
|
||||
3. add_discovery_configs - 添加发现配置
|
||||
4. fix_tag_pool_column - 修复标签池列
|
||||
5. add_discovery_configs_v2 - 发现配置V2
|
||||
6. add_api_providers_and_skills - 添加API提供者和技能
|
||||
7. add_skill_categories - 添加技能分类
|
||||
8. add_pendingtool_category_relation - 添加待审核工具分类关联
|
||||
9. add_hot_score - 添加热度评分
|
||||
10. add_skill_reviews - 添加技能评测表(SkillReview/ReviewGenerationLog)、Skill新增lastReviewedAt/githubStarsHistory字段
|
||||
|
||||
| # | 迁移名 | 日期 | 说明 |
|
||||
|---|--------|------|------|
|
||||
| 1 | init | 2026-04-28 | 初始化核心表(Category/Tool/PendingTool/SystemConfig/User) |
|
||||
| 2 | remove_scraped_at | 2026-05-01 | 移除scrapedAt字段 |
|
||||
| 3 | add_discovery_configs | 2026-05-01 | 添加发现配置 |
|
||||
| 4 | fix_tag_pool_column | 2026-05-01 | 修复标签池列 |
|
||||
| 5 | add_discovery_configs_v2 | 2026-05-02 | 发现配置V2 |
|
||||
| 6 | add_api_providers_and_skills | 2026-05-02 | 添加API提供者和技能(Skill/PendingSkill) |
|
||||
| 7 | add_skill_categories | 2026-05-02 | 添加技能分类(SkillCategory) |
|
||||
| 8 | add_pendingtool_category_relation | 2026-05-02 | 添加PendingTool分类关联 |
|
||||
| 9 | add_hot_score | 2026-05-08 | 添加热度评分(DailyReportItem.hotScore) |
|
||||
| 10 | add_skill_reviews | 2026-05-20 | 添加技能评测表+Skill扩展字段 |
|
||||
| 11 | add_task_system | 2026-05-24 | 添加任务调度系统+权限体系+社区功能 |
|
||||
|
||||
@@ -35,14 +35,59 @@
|
||||
### GET/POST /api/auth/[...nextauth]
|
||||
NextAuth认证端点(登录/回调/CSRF等)。
|
||||
|
||||
### 用户相关API(需NextAuth用户认证)
|
||||
### POST /api/auth/register
|
||||
用户注册(邮箱+密码)。
|
||||
|
||||
### GET /api/categories/[slug]
|
||||
获取分类详情。
|
||||
|
||||
### GET /api/daily-reports
|
||||
获取AI日报列表。
|
||||
|
||||
### GET /api/recommendations
|
||||
获取推荐内容。
|
||||
|
||||
### 评测榜单API(公开)
|
||||
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/skill-reviews | GET | 获取评测列表(分页,仅PUBLISHED) |
|
||||
| /api/skill-reviews/rankings | GET | 获取评测榜单:topByRating(评测分TOP10) + topByStarsChange(Stars涨幅周榜TOP10) |
|
||||
|
||||
---
|
||||
|
||||
## 用户相关API(需NextAuth用户认证)
|
||||
|
||||
### /api/user/profile
|
||||
- GET: 获取当前用户资料
|
||||
- PUT: 更新用户资料
|
||||
|
||||
### /api/user/favorites
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/user/favorites/status | GET | 获取收藏状态 |
|
||||
| /api/user/favorites | GET | 获取当前用户收藏列表(工具+技能) |
|
||||
| /api/user/favorites | POST | 添加收藏(body: { targetType, targetId }) |
|
||||
| /api/user/favorites | DELETE | 取消收藏(body: { targetType, targetId }) |
|
||||
|
||||
### /api/user/history
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/user/history | GET | 获取浏览历史 |
|
||||
| /api/user/history | POST | 记录浏览历史 |
|
||||
|
||||
### /api/user/collections
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/user/collections | GET | 获取收藏夹列表 |
|
||||
| /api/user/collections | POST | 创建收藏夹 |
|
||||
| /api/user/collections/[id] | GET | 获取单个收藏夹详情 |
|
||||
| /api/user/collections/[id] | PUT | 更新收藏夹 |
|
||||
| /api/user/collections/[id] | DELETE | 删除收藏夹 |
|
||||
| /api/user/collections/[id]/items | GET | 获取收藏夹项目 |
|
||||
| /api/user/collections/[id]/items | POST | 添加收藏夹项目 |
|
||||
| /api/user/collections/[id]/items/[itemId] | PUT | 更新收藏夹项目 |
|
||||
| /api/user/collections/[id]/items/[itemId] | DELETE | 删除收藏夹项目 |
|
||||
|
||||
---
|
||||
|
||||
@@ -112,11 +157,21 @@ NextAuth认证端点(登录/回调/CSRF等)。
|
||||
|------|------|------|
|
||||
| /api/admin/discover-tools | POST | 导入工具JSON数组(body: {tools: [...], categoryId}),自动去重导入待审核列表 |
|
||||
| /api/admin/discover-skills | POST | 导入技能JSON数组(body: {skills: [...], categoryId}),自动去重导入待审核列表 |
|
||||
| /api/admin/discover-skills/run | POST | 一键运行技能探索 |
|
||||
| /api/admin/discover-news | POST | 导入新闻JSON数组(body: {items: [...]}),自动生成今日AI日报 |
|
||||
| /api/admin/discover-news | GET | 获取今日AI日报 |
|
||||
| /api/admin/check-tools | POST | 检测工具网站可访问性+抓取缺失Logo(body: {type: "published"/"pending"}),返回logoFetched/logoMethod/logoUrl |
|
||||
| /api/admin/update-stars | POST | 更新GitHub Star数(body: {type: "published"/"pending"}) |
|
||||
|
||||
### 评测管理
|
||||
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/admin/reviews | GET | 获取评测列表 |
|
||||
| /api/admin/reviews/[id] | GET | 获取单个评测详情 |
|
||||
| /api/admin/reviews/[id] | PUT | 更新评测状态 |
|
||||
| /api/admin/reviews/[id]/generate | POST | AI生成评测内容(长文+视频脚本+社交卡片) |
|
||||
|
||||
### 系统配置
|
||||
|
||||
| 路由 | 方法 | 功能 |
|
||||
@@ -124,12 +179,37 @@ NextAuth认证端点(登录/回调/CSRF等)。
|
||||
| /api/admin/system-config | GET | 获取所有配置 |
|
||||
| /api/admin/system-config | PUT | 批量更新配置(upsert) |
|
||||
|
||||
### 评论API(需NextAuth用户认证)
|
||||
### 角色权限管理
|
||||
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/reviews | GET | 获取评论列表(query: type, targetId) |
|
||||
| /api/reviews | POST | 创建评论(body: { type, targetId, content, rating? }) |
|
||||
| /api/admin/roles | GET | 获取所有角色列表 |
|
||||
| /api/admin/roles | POST | 创建角色 |
|
||||
| /api/admin/roles/[id] | PUT | 更新角色 |
|
||||
| /api/admin/roles/[id] | DELETE | 删除角色 |
|
||||
| /api/admin/permissions | GET | 获取全部权限点列表 |
|
||||
| /api/admin/user-permissions | GET | 获取当前用户权限(roleId/userId/当前用户) |
|
||||
|
||||
### 日报管理
|
||||
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/admin/daily-reports | GET | 获取日报列表 |
|
||||
| /api/admin/daily-reports/[id] | GET | 获取单个日报详情 |
|
||||
| /api/admin/daily-reports/[id] | PUT | 更新日报 |
|
||||
| /api/admin/daily-reports/[id] | DELETE | 删除日报 |
|
||||
| /api/admin/daily-reports/generate | POST | AI一键生成日报内容 |
|
||||
|
||||
### 任务调度API(需NextAuth认证)
|
||||
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/admin/tasks/configs | GET | 获取全部6个任务配置(合并TaskConfig+默认值) |
|
||||
| /api/admin/tasks/configs | PUT | 更新/创建任务配置(body: { taskKey, enabled?, cronExpr?, config? }) |
|
||||
| /api/admin/tasks/logs | GET | 获取任务执行日志(分页,query: taskKey?, page, pageSize) |
|
||||
| /api/admin/tasks/run | POST | 手动触发任务执行(body: { taskKey }),通过child_process.exec运行对应脚本 |
|
||||
|
||||
---
|
||||
|
||||
## SystemConfig 配置键
|
||||
|
||||
|
||||
@@ -4,38 +4,53 @@
|
||||
|
||||
### / (首页)
|
||||
- 文件: `src/app/page.tsx`
|
||||
- 组件: HomePageClient
|
||||
- 功能: 搜索框、AI工具分类网格(一级+二级分类,左侧导航+标签切换)、技能分类网格、最新上架工具、热门工具、CTA区块
|
||||
- 数据源: `/api/homepage`, `/api/categories`, `/api/skill-categories`, `/api/tools`
|
||||
|
||||
### /tools (工具列表)
|
||||
- 文件: `src/app/tools/page.tsx`
|
||||
- 功能: 分类筛选侧边栏(一级分类)、定价模型筛选、搜索、分页
|
||||
- 组件: ToolsContent
|
||||
- 功能: 分类筛选侧边栏(一级分类)、定价模型筛选、搜索、分页、卡片网格展示
|
||||
- 数据源: `/api/categories`, `/api/tools`
|
||||
|
||||
### /tools/[slug] (工具详情)
|
||||
- 文件: `src/app/tools/[slug]/page.tsx`
|
||||
- 功能: 工具完整信息展示、浏览计数+1、收藏按钮、评论评价
|
||||
- 功能: 工具完整信息展示、浏览计数+1、收藏按钮、评论评价(ReviewSection)
|
||||
- 数据源: `/api/tools/[slug]`
|
||||
|
||||
### /categories/[slug] (分类详情)
|
||||
- 文件: `src/app/categories/[slug]/page.tsx`
|
||||
- 功能: 按分类slug展示该分类下的工具
|
||||
- 组件: CategoryContent
|
||||
- 功能: 按分类slug展示该分类下的工具,分类标题+工具网格
|
||||
- 数据源: `/api/categories`, `/api/tools`
|
||||
|
||||
### /reviews (评测中心)
|
||||
- 文件: `src/app/reviews/page.tsx`
|
||||
- 组件: ReviewsList, SidebarRankings
|
||||
- 功能: 评测列表展示(主栏)+ 侧边栏榜单(评测分榜TOP10 + Stars涨幅榜TOP10)
|
||||
- 数据源: `/api/skill-reviews`, `/api/skill-reviews/rankings`
|
||||
|
||||
### /skills (技能库)
|
||||
- 文件: `src/app/skills/page.tsx`
|
||||
- 功能: 技能分类筛选(一级+二级分类,左侧导航+标签切换)、搜索
|
||||
- 组件: SkillsPageClient
|
||||
- 功能: 技能分类筛选(一级+二级分类,左侧导航+标签切换)、搜索、分页
|
||||
- 数据源: `/api/skill-categories`, `/api/skills`
|
||||
|
||||
### /skills/[slug] (技能详情)
|
||||
- 文件: `src/app/skills/[slug]/page.tsx`
|
||||
- 功能: 技能完整信息展示、浏览计数+1、收藏按钮、五维评测雷达图(SkillReviewCard)、评论评价
|
||||
- 功能: 技能完整信息展示、浏览计数+1、收藏按钮、五维评测雷达图(SkillReviewCard)、评论评价(ReviewSection)
|
||||
- 数据源: `/api/skills/[slug]`, `/api/skills/[slug]/review`
|
||||
|
||||
### /daily (AI日报)
|
||||
- 文件: `src/app/daily/page.tsx`
|
||||
- 功能: 展示AI日报列表和详情
|
||||
- 数据源: `/api/daily-reports`
|
||||
|
||||
### /login (用户登录)
|
||||
- 文件: `src/app/login/page.tsx`
|
||||
- 功能: 用户邮箱+密码登录/注册,GitHub OAuth登录
|
||||
- 数据源: NextAuth Credentials Provider
|
||||
- 数据源: NextAuth Credentials Provider, GitHub OAuth Provider
|
||||
|
||||
### /user (用户中心)
|
||||
- 文件: `src/app/user/page.tsx`
|
||||
@@ -47,18 +62,30 @@
|
||||
- 功能: 收藏的工具和技能列表,支持筛选和搜索
|
||||
- 数据源: `/api/user/favorites`
|
||||
|
||||
### /user/collections (收藏夹)
|
||||
- 文件: `src/app/user/collections/page.tsx`
|
||||
- 功能: 收藏夹列表管理
|
||||
- 数据源: `/api/user/collections`
|
||||
|
||||
### /user/collections/[id] (收藏夹详情)
|
||||
- 文件: `src/app/user/collections/[id]/page.tsx`
|
||||
- 功能: 单个收藏夹内的工具/技能展示
|
||||
- 数据源: `/api/user/collections/[id]`
|
||||
|
||||
---
|
||||
|
||||
## 后台页面
|
||||
|
||||
### /admin/login (登录)
|
||||
- 文件: `src/app/(admin)/admin/login/page.tsx`
|
||||
- 组件: LoginForm
|
||||
- 功能: 管理员登录表单,CSRF token + 原生POST
|
||||
- 凭证: admin@zhuiguang.ai / admin123
|
||||
|
||||
### /admin/pending (待审核工具)
|
||||
- 文件: `src/app/(admin)/admin/pending/page.tsx`
|
||||
- 功能: 审核列表表格、多选复选框、全选、批量通过/拒绝、抓取缺失Logo/重新抓取全部Logo、编辑弹窗、单个通过/拒绝
|
||||
- 功能: 审核列表表格、多选复选框、全选、批量通过/拒绝、**一键通过全部合格**、抓取缺失Logo/重新抓取全部Logo、编辑弹窗、单个通过/拒绝
|
||||
- 表格新增四项检查状态列:网站 ✓/✗ | Logo ✓/✗ | 描述 ✓/✗ | 分类 ✓/✗
|
||||
- 数据源: `/api/admin/pending`, `/api/admin/pending/batch-publish`, `/api/admin/pending/batch-reject`, `/api/admin/pending/fetch-logos`
|
||||
|
||||
### /admin/pending-skills (待审核技能)
|
||||
@@ -86,6 +113,17 @@
|
||||
- 功能: 技能分类CRUD
|
||||
- 数据源: `/api/admin/skill-categories`
|
||||
|
||||
### /admin/reviews (评测管理)
|
||||
- 文件: `src/app/(admin)/admin/reviews/page.tsx`
|
||||
- 组件: ReviewList, ReviewRow, ReviewStats
|
||||
- 功能: 评测列表、统计卡片(已发布/草稿/平均评分)、单篇评测详情、状态管理
|
||||
- 数据源: `/api/admin/reviews`, `/api/admin/reviews/[id]`
|
||||
|
||||
### /admin/reviews/[id] (评测详情)
|
||||
- 文件: `src/app/(admin)/admin/reviews/[id]/page.tsx`
|
||||
- 功能: 单篇评测详情展示、雷达图、生成内容(长文/视频脚本/社交卡片)
|
||||
- 数据源: `/api/admin/reviews/[id]`
|
||||
|
||||
### /admin/discover-tools (探索AI工具)
|
||||
- 文件: `src/app/(admin)/admin/discover-tools/page.tsx`
|
||||
- 功能: 选分类→复制提示词→粘贴JSON→导入审核列表→抓取Logo
|
||||
@@ -118,6 +156,26 @@
|
||||
- 功能: Logo抓取配置、发现提示词配置等全局设置
|
||||
- 数据源: `/api/admin/system-config`
|
||||
|
||||
### /admin/tasks (任务中心)
|
||||
- 文件: `src/app/(admin)/admin/tasks/page.tsx`
|
||||
- 功能: 6个定时任务总览卡片、各任务启用/禁用开关、手动运行按钮、最近执行状态、Cron表达式展示
|
||||
- 数据源: `/api/admin/tasks/configs`, `/api/admin/tasks/run`
|
||||
|
||||
### /admin/tasks/logs (任务执行日志)
|
||||
- 文件: `src/app/(admin)/admin/tasks/logs/page.tsx`
|
||||
- 功能: 所有任务执行历史列表、按任务筛选、可展开查看result/error详情、分页
|
||||
- 数据源: `/api/admin/tasks/logs`
|
||||
|
||||
### /admin/tasks/[taskKey] (单任务详情)
|
||||
- 文件: `src/app/(admin)/admin/tasks/[taskKey]/page.tsx`
|
||||
- 功能: 单任务统计卡片(成功率/失败率/平均耗时)、历史执行记录(可展开查看输出)、手动运行
|
||||
- 数据源: `/api/admin/tasks/configs`, `/api/admin/tasks/logs`, `/api/admin/tasks/run`
|
||||
|
||||
### /admin/roles (角色权限管理)
|
||||
- 文件: `src/app/(admin)/admin/roles/page.tsx`
|
||||
- 功能: 左侧角色列表 + 右侧按分组的权限勾选网格、新建/删除自定义角色(系统角色受保护)、分组全选/取消全选、保存按钮实时同步到数据库
|
||||
- 数据源: `/api/admin/roles`, `/api/admin/permissions`, `/api/admin/user-permissions`
|
||||
|
||||
---
|
||||
|
||||
## 布局
|
||||
@@ -128,10 +186,13 @@
|
||||
|
||||
### 后台布局
|
||||
- 文件: `src/app/(admin)/admin/layout.tsx`
|
||||
- 结构: 左侧边栏(4组菜单) + 右侧内容区
|
||||
- 结构: 左侧边栏(多组菜单) + 右侧内容区
|
||||
- 菜单分组:
|
||||
- 工具管理: 待审核工具、已发布工具、工具分类
|
||||
- 技能库: 待审核技能、已发布技能、技能分类
|
||||
- 评测管理: 评测管理
|
||||
- AI发现: 探索AI工具、检测AI工具、探索Skill技能、更新Skill技能、AI新闻发现
|
||||
- 系统配置: 系统配置
|
||||
- 任务调度: 任务中心、任务日志
|
||||
- 角色权限: 角色权限管理
|
||||
- 登录页不显示侧边栏
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
#### Header (`src/components/layout/Header.tsx`)
|
||||
- 前台顶部导航栏
|
||||
- Logo + 导航链接(工具库/技能库/分类浏览) + 搜索框 + 登录/用户按钮
|
||||
- Logo + 导航链接(工具库/技能库/评测/日报) + 搜索框 + 登录/用户按钮
|
||||
- 移动端汉堡菜单
|
||||
- 滚动时背景模糊效果(bg-white/80 backdrop-blur-2xl)
|
||||
- 搜索框: bg-muted/50 focus:bg-white focus:ring-2 focus:ring-primary/10
|
||||
- 容器宽度: max-w-[1440px]
|
||||
|
||||
#### Footer (`src/components/layout/Footer.tsx`)
|
||||
- 前台底部页脚
|
||||
@@ -23,11 +24,19 @@
|
||||
|
||||
### 公共组件
|
||||
|
||||
#### HeroBanner (`src/components/common/HeroBanner.tsx`)
|
||||
- 首页横幅组件
|
||||
- 渐变背景 + 渐变文字标题 + CTA按钮
|
||||
|
||||
#### LoginModal (`src/components/common/LoginModal.tsx`)
|
||||
- 登录/注册弹窗,支持模式切换
|
||||
- 邮箱+密码认证,注册可选填昵称
|
||||
- bg-white/95 backdrop-blur-xl
|
||||
|
||||
#### LoginForm (`src/components/common/LoginForm.tsx`)
|
||||
- 登录表单组件
|
||||
- 邮箱+密码输入 + 提交按钮 + 错误提示
|
||||
|
||||
#### SkillReviewCard (五维评测雷达图)
|
||||
- 文件: `src/components/common/SkillReviewCard.tsx`
|
||||
- 用途: 技能详情页展示五维评测雷达图和维度详情卡片
|
||||
@@ -38,10 +47,15 @@
|
||||
- 评分色标: ≥4绿色(emerald) / ≥3黄色(amber) / <3红色(red)
|
||||
- 设计规范: 遵循浅色主题设计系统,紫色(violet)主色调雷达图
|
||||
|
||||
### ReviewSection (`src/components/common/ReviewSection.tsx`)
|
||||
#### ReviewSection (`src/components/common/ReviewSection.tsx`)
|
||||
- 用户评论/评价组件,支持评分和文字评论
|
||||
- 支持tool和skill两种类型
|
||||
- bg-white/80卡片,bg-white/60评论项
|
||||
- 支持嵌套回复、点赞、排序
|
||||
|
||||
#### CommentForm (`src/components/common/CommentForm.tsx`)
|
||||
- 评论输入表单,支持评分选择
|
||||
- 字数限制、评分验证
|
||||
|
||||
#### FavoriteButton (`src/components/common/FavoriteButton.tsx`)
|
||||
- 收藏按钮,乐观更新
|
||||
@@ -56,6 +70,7 @@
|
||||
#### Button (`src/components/ui/button.tsx`)
|
||||
- 6种变体: default, outline, secondary, ghost, destructive, link
|
||||
- 4种尺寸: default, sm, lg, icon
|
||||
- 基于 class-variance-authority
|
||||
|
||||
#### Card (`src/components/ui/card.tsx`)
|
||||
- Card/CardHeader/CardTitle/CardDescription/CardContent/CardFooter
|
||||
@@ -90,6 +105,13 @@
|
||||
- 动画: fade-in, slide-up, float, glow-pulse
|
||||
- 自定义字体: Geist Sans, Geist Mono
|
||||
|
||||
### Next.js配置 (`next.config.mjs`)
|
||||
- 图片域名: remotePatterns 允许所有https域名
|
||||
- 图片格式: avif, webp
|
||||
- 缓存: 静态资源365天不可变,API安全头
|
||||
- 安全头: X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy
|
||||
- Logo缓存: 开发环境no-cache,生产环境1天immutable
|
||||
|
||||
### 设计规范
|
||||
- 圆角: 统一使用 rounded-xl (12px) 或 rounded-2xl (16px)
|
||||
- 边框: border-border/40 (40%透明度)
|
||||
|
||||
@@ -79,19 +79,6 @@ AI发现模块是追光AI的核心功能,采用"提示词+JSON粘贴导入"模
|
||||
- `downloadLogo(url, filename): Promise<string>` — 下载Logo到 `/public/logos/` 目录
|
||||
- 返回本地路径如 `/logos/filename.png`
|
||||
|
||||
## 脚本
|
||||
|
||||
### discover-skills.mjs
|
||||
- 独立运行的AI技能发现脚本
|
||||
- 遍历20个技能分类,每类调用DeepSeek API推荐10个GitHub开源项目
|
||||
- 通过 `/api/admin/pending-skills/batch` 批量导入
|
||||
- 每分类间隔3秒避免限流
|
||||
- 自动排除已收录技能
|
||||
|
||||
### import-tools-batch1.mjs / import-tools-batch2.mjs
|
||||
- 硬编码的AI工具数据导入脚本
|
||||
- 通过 `/api/admin/pending/batch` 批量导入
|
||||
|
||||
## 自动化评测流程
|
||||
|
||||
### 架构概览
|
||||
@@ -105,14 +92,6 @@ Prisma → Skill记录 + SkillReview记录 + ReviewGenerationLog日志
|
||||
前端 → /api/skills/[slug]/review → SkillReviewCard雷达图展示
|
||||
```
|
||||
|
||||
### 评测脚本 (scripts/auto-review.mjs)
|
||||
- 搜索关键词: ai agent, llm framework, rag, prompt engineering
|
||||
- 每日限制: 8个项目 (DAILY_LIMIT可配置)
|
||||
- 最低Star数: 500
|
||||
- 去重: 通过sourceUrl检查是否已存在
|
||||
- 综合分校验: 自动计算五维均分,偏差>0.3时修正
|
||||
- 评测状态: 初始为DRAFT,需手动或通过脚本改为PUBLISHED
|
||||
|
||||
### 五维评测维度
|
||||
| 维度 | 字段 | 说明 |
|
||||
|------|------|------|
|
||||
@@ -125,8 +104,57 @@ Prisma → Skill记录 + SkillReview记录 + ReviewGenerationLog日志
|
||||
### 评测标签分类
|
||||
LLM框架, Agent框架, RAG, 提示工程, 多模态, 代码助手, 模型训练, 数据工程, 部署工具, 评测工具, 安全对齐, 其他
|
||||
|
||||
### 发布评测脚本 (scripts/publish-reviews.mjs)
|
||||
- 将DRAFT状态评测改为PUBLISHED
|
||||
- 同时将对应Skill状态从draft改为published
|
||||
## 定时任务自动化(Task调度系统)
|
||||
|
||||
## 踩坑记录
|
||||
### 架构概览
|
||||
```
|
||||
Crontab(6个定时) → 脚本执行(Node.js .mjs) → 外部API调用(GitHub/DeepSeek/网站)
|
||||
↓
|
||||
Prisma → Tool/Skill/PendingTool/PendingSkill/DailyReport 写入
|
||||
↓
|
||||
TaskLog表记录执行结果(status/duration/result/error)
|
||||
↓
|
||||
后台管理 /admin/tasks → 查看配置/状态/历史/手动触发
|
||||
```
|
||||
|
||||
### 7个任务总览
|
||||
|
||||
| # | 任务 | 脚本 | Cron | 依赖外部API | 产量 |
|
||||
|---|------|------|------|------------|------|
|
||||
| Task1 | 发现AI工具 | task1-discover-tools.mjs | 06:00 | DeepSeek + RSS抓取 | 不定 |
|
||||
| Task3 | 工具巡检 | task3-check-tools.mjs | 03:00 | 网站GET请求 | 全部Tool+PendingTool |
|
||||
| Task4 | 发现AI技能 | daily-discover.mjs | 05:00 | GitHub API + DeepSeek | ≤30/天 (stars≥1000) |
|
||||
| Task5 | 更新星值 | task5-update-stars.mjs | 01:00 | GitHub API | 全部GitHub技能 |
|
||||
| Task6 | 评测热门 | task6-review-hot.mjs | 04:00 | GitHub API + DeepSeek | 2个/天 |
|
||||
| - | AI日报 | daily-news.mjs | 07:30 | RSS多源 + DeepSeek | 1篇/天 |
|
||||
|
||||
### TaskLog 统一记录
|
||||
所有任务脚本统一在末尾写入TaskLog:
|
||||
```javascript
|
||||
await prisma.taskLog.create({
|
||||
data: { taskKey: "taskX-xxx", taskName: "任务名", status: "completed",
|
||||
startedAt, finishedAt, duration, result, error }
|
||||
});
|
||||
```
|
||||
失败时在 catch 块中写入 status: "failed" 的日志。
|
||||
|
||||
### 后台可视化
|
||||
- `/admin/tasks` — 6个任务卡片,显示启用状态/Cron/最近执行/手动运行
|
||||
- `/admin/tasks/logs` — 全部执行历史,按任务筛选,可展开查看结果详情
|
||||
- `/admin/tasks/[taskKey]` — 单任务详情,统计成功率/失败率/平均耗时
|
||||
|
||||
## 质量过滤
|
||||
|
||||
### isValidAIProject()
|
||||
- 关键词过滤: `book/guide/tutorial/awesome/interview/notes/handbook/cheatsheet/roadmap/curated-list` 等
|
||||
- 语言过滤: 纯Markdown/HTML文档Repo(Stars<5000)自动拒绝
|
||||
- 主题过滤: 有GitHub Topics的Repo必须包含AI相关Topic(ai/llm/rag/agent/gpt等)
|
||||
|
||||
## AI日报新闻源
|
||||
- **36kr** RSS (https://36kr.com/feed) — 国内科技资讯
|
||||
- **IT之家** RSS (https://www.ithome.com/rss/) — 国内科技资讯
|
||||
- **开源中国** RSS (https://www.oschina.net/news/rss) — 开源动态
|
||||
- **HackerNews** API — 海外AI/技术热点
|
||||
- **Google News** RSS — 海外新闻(国内服务器可能无法访问)
|
||||
- 流程: 搜索真实新闻 → AI关键词过滤 → 近2天筛选 → DeepSeek整理格式 → 入库发布
|
||||
- **严禁让DeepSeek直接生成新闻内容**(会编造假新闻),必须基于真实新闻素材整理
|
||||
|
||||
@@ -2,25 +2,45 @@
|
||||
|
||||
## 技术栈
|
||||
- NextAuth.js v4
|
||||
- Credentials Provider(用户名密码 + 用户邮箱密码)
|
||||
- Credentials Provider(用户邮箱密码)
|
||||
- GitHub OAuth Provider
|
||||
- JWT Session策略
|
||||
- bcrypt 密码加密
|
||||
|
||||
## 配置 (`src/lib/auth.ts`)
|
||||
|
||||
### 管理员认证
|
||||
- 唯一凭证: `admin@zhuiguang.ai` / `admin123`
|
||||
- 硬编码在auth.ts中,非数据库查询
|
||||
|
||||
### 用户认证
|
||||
- 邮箱+密码注册/登录
|
||||
- 用户数据存储在User表
|
||||
- 密码bcrypt加密
|
||||
- GitHub OAuth登录(自动创建/关联用户)
|
||||
- 登录频率限制: 7次/分钟
|
||||
|
||||
### 登录流程
|
||||
1. 用户输入邮箱+密码
|
||||
2. 检查登录频率限制
|
||||
3. 查询User表获取用户
|
||||
4. bcrypt.compare验证密码
|
||||
5. 返回用户信息(id, email, name, role)
|
||||
6. JWT回调将用户信息加入token
|
||||
7. Session回调将token信息传递给session
|
||||
|
||||
### GitHub OAuth流程
|
||||
1. 用户点击GitHub登录
|
||||
2. 重定向到GitHub授权
|
||||
3. 回调获取profile信息
|
||||
4. 检查oauthProvider+oauthId是否已存在
|
||||
5. 不存在则创建新用户
|
||||
6. 返回用户信息
|
||||
|
||||
### Session策略
|
||||
- 使用JWT,不使用数据库session
|
||||
- JWT密钥: `NEXTAUTH_SECRET` 环境变量
|
||||
- Session有效期: 30天
|
||||
- Token包含: id, role
|
||||
|
||||
### 回调函数
|
||||
- `signIn`: GitHub OAuth自动创建用户
|
||||
- `jwt`: 登录时将用户信息加入token
|
||||
- `session`: 将token中的用户信息传递给session
|
||||
|
||||
@@ -28,31 +48,67 @@
|
||||
|
||||
### 保护规则
|
||||
- 保护 `/admin` 下所有路由
|
||||
- 保护 `/api/admin/:path*` 路由
|
||||
- 保护 `/api/user/:path*` 路由
|
||||
- 跳过 `/admin/login`
|
||||
- 使用NextAuth middleware进行认证检查
|
||||
|
||||
### 登录流程
|
||||
1. 访问 `/admin/*` → middleware检查session
|
||||
2. 未登录 → 重定向到 `/admin/login`
|
||||
3. 登录页提交表单 → Server Action验证凭证
|
||||
4. 验证成功 → 重定向到 `/admin`
|
||||
### 权限检查
|
||||
- 检查token是否存在
|
||||
- 检查role是否为admin或vip
|
||||
- 未登录重定向到 /admin/login
|
||||
- 无权限返回401/403
|
||||
|
||||
## 管理员API认证 (`src/lib/admin-auth.ts`)
|
||||
|
||||
### getAdminSession
|
||||
- 获取当前会话
|
||||
- 验证用户角色
|
||||
- 支持role字符串和roleId双重验证
|
||||
- 缓存机制(React cache)
|
||||
|
||||
### requireAdmin中间件
|
||||
- 所有 `/api/admin/` 路由必须使用requireAdmin中间件
|
||||
- 验证流程: 检查session → 验证邮箱是否为admin@zhuiguang.ai
|
||||
- 已覆盖28个后台API端点
|
||||
- 验证流程: 检查session → 验证角色
|
||||
- 返回401/403错误响应
|
||||
|
||||
### getUserPermissionKeys
|
||||
- 获取用户权限键集合
|
||||
- 基于roleId关联Role表查询
|
||||
- 缓存机制
|
||||
|
||||
### requirePermission
|
||||
- 细粒度权限点校验
|
||||
- 检查permissionKeys是否包含指定key
|
||||
- 返回403如果缺少权限
|
||||
|
||||
### getAllUserPermissions
|
||||
- 获取当前用户全部权限集合
|
||||
- 支持admin角色(返回全部权限)
|
||||
- 支持roleId关联角色
|
||||
|
||||
## 前端权限Hook (`src/lib/use-permission.ts`)
|
||||
|
||||
### usePermission
|
||||
- 客户端Hook
|
||||
- 获取当前用户权限
|
||||
- 缓存机制
|
||||
- 提供方法:
|
||||
- `can(key)` — 检查单个权限
|
||||
- `canAny(keys)` — 检查任一权限
|
||||
- `canAll(keys)` — 检查全部权限
|
||||
- `refresh` — 刷新权限
|
||||
|
||||
## 登录页
|
||||
- 管理员登录: `src/app/(admin)/admin/login/page.tsx` (原生HTML表单 + CSRF Token)
|
||||
- 用户登录: `src/app/login/page.tsx` (NextAuth Credentials + GitHub OAuth)
|
||||
- 用户登录弹窗: `src/components/common/LoginModal.tsx`
|
||||
- 登录表单: `src/components/common/LoginForm.tsx`
|
||||
|
||||
## 环境变量
|
||||
```
|
||||
NEXTAUTH_URL=http://localhost:3100
|
||||
NEXTAUTH_SECRET=<secret>
|
||||
GITHUB_ID=<github-oauth-id>
|
||||
GITHUB_SECRET=<github-oauth-secret>
|
||||
NEXTAUTH_URL=http://localhost:8301
|
||||
NEXTAUTH_SECRET=zhuiguang-ai-dev-secret
|
||||
GITHUB_CLIENT_ID=<github-oauth-client-id>
|
||||
GITHUB_CLIENT_SECRET=<github-oauth-secret>
|
||||
```
|
||||
|
||||
@@ -2,103 +2,184 @@
|
||||
|
||||
## 工具库 (`src/lib/`)
|
||||
|
||||
### src/lib/github.ts (GitHub数据采集)
|
||||
### prisma.ts - 数据库客户端
|
||||
- Prisma单例模式,防止开发环境热重载创建多实例
|
||||
- 使用PrismaMariaDb adapter
|
||||
- 连接池配置(connection_limit=20, pool_timeout=30)
|
||||
- 日志: 开发环境warn/error,生产环境error
|
||||
|
||||
### auth.ts - 认证配置
|
||||
- NextAuth配置导出
|
||||
- Credentials Provider(用户邮箱密码)
|
||||
- GitHub OAuth Provider
|
||||
- JWT策略
|
||||
- 登录频率限制(7次/分钟)
|
||||
- 导出GET/POST handler
|
||||
|
||||
### admin-auth.ts - 管理员API认证
|
||||
- 导出 `getAdminSession()` — 获取当前会话(带缓存)
|
||||
- 导出 `requireAdmin()` — 管理员权限验证中间件
|
||||
- 导出 `requirePermission(key)` — 细粒度权限点校验
|
||||
- 导出 `getAllUserPermissions()` — 获取当前用户全部权限
|
||||
- 导出 `getUserPermissionKeys(userId)` — 获取用户权限键集合
|
||||
- 验证session中角色和权限
|
||||
- 返回401/403错误响应
|
||||
|
||||
### utils.ts - 工具函数
|
||||
- `cn(...inputs)` — 合并clsx + tailwind-merge的className工具
|
||||
- `extractJSON(str)` — JSON提取工具,支持markdown代码块包裹、花括号/方括号容错
|
||||
|
||||
### validation.ts - 数据验证
|
||||
- Zod验证schemas
|
||||
- 包含: registerSchema, loginSchema, paginationSchema, toolImportSchema, skillImportSchema, newsImportSchema, checkTypeSchema, profileUpdateSchema, favoriteSchema, historySchema, taskRunSchema, roleCreateSchema, categoryCreateSchema, skillCategoryCreateSchema, systemConfigUpdateSchema
|
||||
|
||||
### deepseek.ts - DeepSeek评测生成
|
||||
- 依赖: openai (兼容OpenAI接口)
|
||||
- 认证: process.env.DEEPSEEK_API_KEY
|
||||
- baseURL: https://api.deepseek.com/v1
|
||||
- 模型: deepseek-v4-pro
|
||||
- `generateReview(repoName, description, stars, license, readme)`: 调用DeepSeek生成五维评测
|
||||
- 综合分校验: 自动计算五维均分,偏差>0.3时修正
|
||||
- JSON提取: 兼容markdown代码块包裹的响应
|
||||
|
||||
### github.ts - GitHub数据采集
|
||||
- 依赖: octokit
|
||||
- 认证: process.env.GITHUB_TOKEN (可选,提升限流60→5000次/小时)
|
||||
- `searchHotRepos(query, minStars, maxResults)`: 搜索热门仓库,按Star降序
|
||||
- `getRepoReadme(owner, repo)`: 获取仓库README内容(base64解码)
|
||||
- `GitHubRepo` 接口: id, full_name, html_url, description, stargazers_count, forks_count, language, license, topics, updated_at, readme
|
||||
|
||||
### src/lib/deepseek.ts (DeepSeek评测生成)
|
||||
- 依赖: openai (兼容OpenAI接口)
|
||||
- 认证: process.env.DEEPSEEK_API_KEY
|
||||
- baseURL: https://api.deepseek.com/v1
|
||||
- 模型: deepseek-v4-pro
|
||||
- `generateReview(repoName, description, stars, license, readme)`: 调用DeepSeek生成五维评测
|
||||
- `ReviewDimension` 接口: { score, summary, detail }
|
||||
- `ReviewResult` 接口: capability, devExp, costLicense, community, performance, overall, tags
|
||||
- 综合分校验: 自动计算五维均分,偏差>0.3时修正
|
||||
- JSON提取: 兼容markdown代码块包裹的响应
|
||||
|
||||
### prisma.ts - 数据库客户端
|
||||
- Prisma单例模式,防止开发环境热重载创建多实例
|
||||
- 使用PrismaMariaDb adapter
|
||||
- 连接池配置
|
||||
|
||||
### auth.ts - 认证配置
|
||||
- NextAuth配置导出
|
||||
- Credentials Provider(管理员+用户)
|
||||
- JWT策略
|
||||
- GitHub OAuth Provider
|
||||
- 导出GET/POST handler
|
||||
|
||||
### admin-auth.ts - 管理员API认证
|
||||
- 导出 `requireAdmin()` 中间件函数
|
||||
- 验证session中邮箱是否为admin@zhuiguang.ai
|
||||
- 所有 `/api/admin/` 路由必须使用此中间件
|
||||
- 返回401/403错误响应
|
||||
|
||||
### utils.ts - 工具函数
|
||||
- `cn()`: 合并clsx + tailwind-merge的className工具
|
||||
|
||||
### logo-fetcher.ts - Logo抓取引擎
|
||||
- 导出 `fetchLogo(websiteUrl, html?): Promise<string>` — 返回Logo URL
|
||||
- 导出 `fetchLogoWithMethod(websiteUrl, html?): Promise<LogoFetchResult>` — 返回 `{url, method}`
|
||||
- 10种抓取策略按优先级执行
|
||||
- 支持从SystemConfig读取配置
|
||||
- 每种成功方法返回中文名称(如"HTML Link图标"、"OG/Twitter图片"等)
|
||||
- 详见 [05-ai-discovery.md](./05-ai-discovery.md)
|
||||
- 每种成功方法返回中文名称
|
||||
|
||||
### logo-storage.ts - Logo本地存储
|
||||
- 导出 `downloadLogo(url, filename): Promise<string>`
|
||||
- 下载远程Logo到 `/public/logos/` 目录
|
||||
- 返回本地路径如 `/logos/filename.png`
|
||||
|
||||
### rate-limit.ts - 频率限制
|
||||
- `rateLimit(ip, maxRequests, windowMs)` — IP频率限制
|
||||
- 内存存储(Map)
|
||||
- 默认: 10次/分钟
|
||||
|
||||
### use-permission.ts - 前端权限Hook
|
||||
- 客户端Hook
|
||||
- 获取当前用户权限
|
||||
- 提供 `can(key)`, `canAny(keys)`, `canAll(keys)` 方法
|
||||
|
||||
---
|
||||
|
||||
## 脚本 (`scripts/`)
|
||||
|
||||
### discover-skills.mjs - AI技能发现
|
||||
- 独立运行的Node.js脚本
|
||||
- 遍历20个技能分类,每类调用DeepSeek API推荐10个GitHub开源项目
|
||||
- 通过 `/api/admin/pending-skills/batch` 批量导入
|
||||
- 自动排除已收录技能
|
||||
- 每分类间隔3秒
|
||||
- 运行: `node scripts/discover-skills.mjs`
|
||||
### 定时任务脚本(6个 + 1个日报,均含TaskLog记录)
|
||||
|
||||
### import-tools-batch1.mjs - 第一批工具导入
|
||||
- 硬编码约80个国产AI工具
|
||||
- 分类: 文本生成(165)/图像生成(174)/视频生成(183)/音频与语音(191)
|
||||
#### task1-discover-tools.mjs — Task1 发现AI工具
|
||||
- 每天06:00由Crontab触发
|
||||
- 从36kr/IT之家/开源中国RSS抓取新闻,调用DeepSeek提取AI工具信息
|
||||
- 去重后入库PendingTool,含checkWebsiteOk/checkLogoOk等巡检结果
|
||||
- 结果写入TaskLog(taskKey: task1-discover-tools)
|
||||
|
||||
### import-tools-batch2.mjs - 第二批工具导入
|
||||
- 硬编码约200个国产AI工具
|
||||
- 分类: 代码开发/AI Agent/办公效率/设计创意/营销SEO/数据分析/教育学习/搜索信息/安全合规/医疗健康/金融法律/电商零售/3D游戏/科学研究/模型框架/聊天机器人
|
||||
#### task3-check-tools.mjs — Task3 工具巡检
|
||||
- 每天03:00由Crontab触发
|
||||
- 检查所有已发布Tool网站可访问性+Logo有效性,更新websiteOk/logoOk字段
|
||||
- 对PendingTool逐一检查,四项检查全部通过则自动发布为正式Tool
|
||||
- 结果写入TaskLog(taskKey: task3-check-tools),含websiteFails/logoFails/autoPublished统计
|
||||
|
||||
#### task4 daily-discover.mjs — Task4 发现AI技能
|
||||
- 每天05:00由Crontab触发
|
||||
- GitHub搜索AI相关项目(stars≥1000,日上限30)
|
||||
- DeepSeek预评测后入库**PendingSkill**(不是直接创建Skill)
|
||||
- 去重检查: skill表 + pendingSkill表
|
||||
- 仓库内容质量过滤(isValidAIProject): 排除文档/教程/面试题/书单类Repo
|
||||
- 结果写入TaskLog(taskKey: task4-discover-skills),含discovered/skipped/reviewed/failed统计
|
||||
|
||||
#### task5-update-stars.mjs — Task5 更新技能星值
|
||||
- 每天01:00由Crontab触发
|
||||
- 查询所有sourceUrl含github.com的Skill
|
||||
- 通过Octokit API获取最新stargazers_count
|
||||
- 更新githubStars/starsChangeDay/starsChangeWeek/starsChangeMonth
|
||||
- 维护githubStarsHistory数组(保留最近90天)
|
||||
- 结果写入TaskLog(taskKey: task5-update-stars),含updated/failed/skipped统计
|
||||
|
||||
#### task6-review-hot.mjs — Task6 评测热门技能
|
||||
- 每天04:00由Crontab触发
|
||||
- 查找2个已发布但无SkillReview的最热门GitHub技能(按githubStars/viewCount排序)
|
||||
- 获取GitHub README,调用DeepSeek API生成五维评测
|
||||
- 创建SkillReview(status: PUBLISHED),更新Skill.lastReviewedAt
|
||||
- 结果写入TaskLog(taskKey: task6-review-hot),含reviewed/failed统计
|
||||
|
||||
#### daily-news.mjs — AI日报生成
|
||||
- 每天07:30由Crontab触发
|
||||
- 多源搜索: 36kr RSS + IT之家 RSS + 开源中国 RSS + HackerNews API + Google News RSS
|
||||
- 新闻过滤: 发布日期近2天内 + AI关键词匹配
|
||||
- DeepSeek整理格式生成中文日报(标题+摘要+条目)
|
||||
- 入库DailyReport表
|
||||
- 结果写入TaskLog(taskKey: daily-news),含reportId/itemCount/title统计
|
||||
|
||||
#### seed-task-configs.mjs — 任务配置种子数据
|
||||
- 一次性运行(幂等,创建或更新)
|
||||
- 初始化6个TaskConfig记录(task1/3/4/5/6 + daily-news)
|
||||
- 含默认cronExpr、enabled=true、description
|
||||
|
||||
### 其他脚本
|
||||
|
||||
#### auto-review.mjs (自动化评测脚本 — 已被Task4/Task6替代)
|
||||
- 依赖: @prisma/client, @prisma/adapter-mariadb, octokit, openai
|
||||
- 流程: GitHub搜索→README获取→DeepSeek评测→Skill入库→SkillReview入库→日志记录
|
||||
- 配置: SEARCH_QUERIES(4个关键词), MIN_STARS(500→已被Task4提升为1000), DAILY_LIMIT(8→已有Task4用的30)
|
||||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node scripts/auto-review.mjs`
|
||||
|
||||
#### publish-reviews.mjs (发布评测脚本)
|
||||
- 将DRAFT状态SkillReview改为PUBLISHED
|
||||
- 将对应draft状态Skill改为published
|
||||
- 注: Task6-review-hot.mjs 创建的SkillReview直接为PUBLISHED,无需此脚本
|
||||
|
||||
#### generate-review-content.mjs (生成评测内容)
|
||||
- 调用DeepSeek生成评测长文、视频脚本、社交卡片
|
||||
- 用于已评测技能的内容生成
|
||||
|
||||
#### organize-content.mjs (内容整理脚本)
|
||||
- 整理和归类内容
|
||||
|
||||
#### test-github.mjs (GitHub API测试)
|
||||
- 测试searchHotRepos和getRepoReadme功能
|
||||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node -r dotenv/config scripts/test-github.mjs`
|
||||
|
||||
#### test-deepseek.mjs (DeepSeek API测试)
|
||||
- 测试generateReview功能,使用langflow作为测试用例
|
||||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node scripts/test-deepseek.mjs`
|
||||
|
||||
#### test-content-generation.mjs (内容生成测试)
|
||||
- 测试评测内容生成管线
|
||||
|
||||
#### debug-json.mjs (JSON解析调试)
|
||||
- 调试JSON解析逻辑
|
||||
|
||||
#### delete-drafts.mjs (删除草稿)
|
||||
- 批量删除草稿数据
|
||||
|
||||
#### cleanup-non-ai.mjs (清理非AI项目)
|
||||
- 清理误入库的非AI技能数据
|
||||
- 使用isValidAIProject过滤
|
||||
|
||||
#### db-status.mjs (数据库状态)
|
||||
- 检查数据库连接和数据状态
|
||||
|
||||
#### seed-permissions.mjs (权限种子数据)
|
||||
- 初始化全部权限点+角色
|
||||
- 幂等运行
|
||||
|
||||
#### migrate-logos.mjs (Logo迁移)
|
||||
- 迁移Logo到本地存储
|
||||
|
||||
---
|
||||
|
||||
## 运维脚本
|
||||
|
||||
### scripts/auto-review.mjs (自动化评测脚本)
|
||||
- 依赖: @prisma/client, @prisma/adapter-mariadb, octokit, openai
|
||||
- 流程: GitHub搜索→README获取→DeepSeek评测→Skill入库→SkillReview入库→日志记录
|
||||
- 配置: SEARCH_QUERIES(4个关键词), MIN_STARS(500), MAX_PER_QUERY(5), DAILY_LIMIT(8)
|
||||
- 去重: 通过sourceUrl检查
|
||||
- slug生成: repo full_name转小写+连字符
|
||||
- 默认分类ID: 120 (AI/ML工程)
|
||||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node scripts/auto-review.mjs`
|
||||
|
||||
### scripts/publish-reviews.mjs (发布评测脚本)
|
||||
- 将DRAFT状态SkillReview改为PUBLISHED
|
||||
- 将对应draft状态Skill改为published
|
||||
|
||||
### scripts/test-github.mjs (GitHub API测试)
|
||||
- 测试searchHotRepos和getRepoReadme功能
|
||||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node -r dotenv/config scripts/test-github.mjs`
|
||||
|
||||
### scripts/test-deepseek.mjs (DeepSeek API测试)
|
||||
- 测试generateReview功能,使用langflow作为测试用例
|
||||
- 运行: `$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; node scripts/test-deepseek.mjs`
|
||||
|
||||
### restart.ps1 - 服务重启
|
||||
- PowerShell脚本
|
||||
- 扫描8301-8310端口
|
||||
@@ -108,3 +189,11 @@
|
||||
|
||||
### temp_clear.mjs - 临时清理
|
||||
- 清空pending_tools表
|
||||
|
||||
### cron脚本 (shell)
|
||||
- `cron-daily-discover.sh` — 每日技能发现
|
||||
- `cron-daily-news.sh` — 每日新闻发现
|
||||
- `cron-task1.sh` — Task1定时任务
|
||||
|
||||
### lib/retry.mjs
|
||||
- 重试工具函数
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
# 社区功能模块
|
||||
|
||||
## 概述
|
||||
社区功能模块包含评论系统、收藏系统、浏览历史、收藏夹、通知系统和论坛板块,为用户提供完整的互动体验。
|
||||
|
||||
## 数据模型
|
||||
|
||||
### PointsHistory (积分历史) 🆕
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @map("user_id") | 用户ID |
|
||||
| points | Int | 积分变动 |
|
||||
| reason | String @db.VarChar(50) | 积分原因 |
|
||||
| detail | String? @db.VarChar(200) | 详细信息 |
|
||||
| refType | String? @map("ref_type") @db.VarChar(50) | 关联类型 |
|
||||
| refId | Int? @map("ref_id") | 关联ID |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: user → User
|
||||
|
||||
**索引**: [userId, createdAt]
|
||||
|
||||
### Comment (评论/回复)
|
||||
- 支持对Tool和Skill进行评论
|
||||
- 支持嵌套回复(通过parentId自引用)
|
||||
- 支持评分(1-5星)
|
||||
- 支持点赞和置顶
|
||||
|
||||
**字段**: id, userId, toolId, skillId, parentId, content, rating, likeCount, isPinned, status, createdAt, updatedAt
|
||||
|
||||
**关系**:
|
||||
- user: User — 用户评论
|
||||
- tool: Tool — 工具评论
|
||||
- skill: Skill — 技能评论
|
||||
- parent/replies: Comment → Comment — 嵌套回复(自引用)
|
||||
- likes: CommentLike[] — 点赞列表
|
||||
|
||||
### CommentLike (评论点赞) - 联合唯一约束 [commentId, userId]
|
||||
|
||||
### Notification (通知)
|
||||
**通知类型**:
|
||||
- COMMENT_REPLY — 评论回复通知
|
||||
- COMMENT_LIKE — 评论点赞通知
|
||||
- TOPIC_REPLY — 话题回复通知
|
||||
- SYSTEM — 系统通知
|
||||
|
||||
### ForumCategory (论坛板块) - 二级分类结构 🆕
|
||||
- **自引用关系**: parent/children (CategoryHierarchy)
|
||||
- **6个父分类 + 24个子分类**
|
||||
- **种子脚本**: `scripts/seed-forum-categories.mjs`, `scripts/fix-forum-categories.mjs`
|
||||
|
||||
**父分类**:
|
||||
| 板块 | Slug | 图标 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 综合讨论区 | general | 💬 | AI话题综合交流 |
|
||||
| AI工具 | ai-tools | 🤖 | AI工具推荐、测评与讨论 |
|
||||
| 开源技能 | skills | ⚡ | 开源AI框架、模型与工具技能 |
|
||||
| 技术深度 | tech | 🔧 | AI技术深度探讨 |
|
||||
| 教程与分享 | tutorials | 📚 | 教程、指南与经验分享 |
|
||||
| 社区互动 | social | 🎪 | 社区活动与交流 |
|
||||
|
||||
**AI工具子分类**: 聊天写作/图像创作/视频音频/代码编程/效率办公/数据分析/教育学习
|
||||
**开源技能子分类**: LLM框架/Agent框架/RAG技术/模型训练/部署推理/多模态/数据工程
|
||||
**综合讨论子分类**: 新手入门/AI资讯/观点讨论
|
||||
**技术深度子分类**: 算法原理/模型评测/安全对齐/硬件加速
|
||||
**教程与分享子分类**: 入门教程/实战项目/最佳实践
|
||||
**社区互动子分类**: 求助问答/求职招聘/闲聊灌水/反馈建议
|
||||
|
||||
### ForumTopic (论坛话题)
|
||||
- 字段: categoryId, userId, title, slug, content, isPinned, isLocked, viewCount, replyCount, lastReplyAt
|
||||
- 全文索引: [title],联合索引: [categoryId, lastReplyAt]
|
||||
|
||||
### ForumPost (论坛回复) 🆕
|
||||
- 字段: topicId, userId, content, **isAnswer** (标记最佳回答), createdAt, updatedAt
|
||||
- onDelete: Cascade(话题删除时自动清理回复)
|
||||
|
||||
### Favorite (收藏) - 联合唯一约束 [userId, toolId], [userId, skillId]
|
||||
### BrowsingHistory (浏览历史) - 自动记录浏览的Tool和Skill
|
||||
### Collection (收藏夹) / CollectionItem (收藏夹项目) - 用户可创建多个收藏夹
|
||||
|
||||
---
|
||||
|
||||
## 🆕 积分体系
|
||||
|
||||
### 积分规则
|
||||
| 行为 | 积分 | 每日上限 |
|
||||
|------|------|----------|
|
||||
| 发表评论 | +5 | 50 |
|
||||
| 评论被点赞 | +2 | 20 |
|
||||
| 发布论坛话题 | +10 | 无限制 |
|
||||
| 论坛回复 | +5 | 30 |
|
||||
| 发表评价 | +8 | 20 |
|
||||
| 每日登录 | +1 | 1 |
|
||||
|
||||
### 等级系统 - 20级成长体系 🆕 (类似QQ)
|
||||
| 等级 | 最低积分 | 徽章 | 每日限额 |
|
||||
|------|----------|------|----------|
|
||||
| LV01 | 0 | ⭐ | 50 |
|
||||
| LV02 | 10 | ⭐ | 80 |
|
||||
| LV03 | 30 | ⭐⭐ | 100 |
|
||||
| LV04 | 60 | ⭐⭐ | 120 |
|
||||
| LV05 | 100 | ⭐⭐ | 150 |
|
||||
| LV06 | 200 | ⭐⭐⭐ | 180 |
|
||||
| LV07 | 400 | ⭐⭐⭐ | 200 |
|
||||
| LV08 | 700 | ⭐⭐⭐ | 250 |
|
||||
| LV09 | 1000 | ⭐⭐⭐ | 300 |
|
||||
| LV10 | 1500 | 🌟 | 400 |
|
||||
| LV11 | 2000 | 🌟 | 500 |
|
||||
| LV12 | 3000 | 🌟 | 600 |
|
||||
| LV13 | 4500 | 🌟 | 700 |
|
||||
| LV14 | 6000 | 🌟🌟 | 800 |
|
||||
| LV15 | 8000 | 🌟🌟 | 1000 |
|
||||
| LV16 | 11000 | 🌟🌟 | 1200 |
|
||||
| LV17 | 15000 | 🌟🌟 | 1500 |
|
||||
| LV18 | 20000 | 🌟🌟🌟 | 1800 |
|
||||
| LV19 | 30000 | 🌟🌟🌟 | 2000 |
|
||||
| LV20 | 50000 | 🌟🌟🌟 | 3000 |
|
||||
|
||||
**旧等级迁移映射**: BRONZE→LV01, SILVER→LV03, GOLD→LV06, PLATINUM→LV10
|
||||
|
||||
### 积分奖励系统
|
||||
- `src/lib/level-config.ts` — 等级配置(客户端安全,无Prisma依赖)
|
||||
- `src/lib/points-reward.ts` — 积分奖励引擎(服务端,含Prisma操作)
|
||||
- `rewardPoints()` — 自动发放积分 + 日限额检查
|
||||
- `getUserStats()` — 获取用户综合统计(积分/评论数/话题数等)
|
||||
- `getUserPointsHistory()` — 积分历史分页查询
|
||||
|
||||
---
|
||||
|
||||
## API接口
|
||||
|
||||
### 评论API (🆕 全新实现)
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/comments | GET | 获取评论列表(支持 toolId/skillId 筛选,含用户等级/积分信息) |
|
||||
| /api/comments | POST | 创建评论(自动积分奖励,父评论作者自动通知) |
|
||||
| /api/comments/[id]/like | POST | 评论点赞/取消点赞(切换模式,被赞者+2分,自动通知) |
|
||||
|
||||
### 论坛API (🆕 全新实现)
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/forum/categories | GET | 获取论坛板块列表 |
|
||||
| /api/forum/topics | GET | 话题列表(按板块/搜索/排序:latest/hot/active) |
|
||||
| /api/forum/topics | POST | 创建话题(+10分) |
|
||||
| /api/forum/topics/[id] | GET | 话题详情(浏览数+1) |
|
||||
| /api/forum/topics/[id] | PUT | 编辑话题(仅作者) |
|
||||
| /api/forum/topics/[id] | DELETE | 删除话题(仅作者) |
|
||||
| /api/forum/topics/[id]/posts | GET | 回复列表 |
|
||||
| /api/forum/topics/[id]/posts | POST | 创建回复(+5分,话题作者自动通知) |
|
||||
| /api/forum/topics/[id]/posts/[postId] | PUT | 编辑回复(仅作者) |
|
||||
| /api/forum/topics/[id]/posts/[postId] | DELETE | 删除回复(仅作者) |
|
||||
|
||||
### 通知API (🆕 全新实现)
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/notifications | GET | 获取通知列表(含未读数) |
|
||||
| /api/notifications | PUT | 标记通知为已读(支持指定ids或全部已读) |
|
||||
|
||||
### 用户积分API (🆕 全新实现)
|
||||
| 路由 | 方法 | 功能 |
|
||||
|------|------|------|
|
||||
| /api/user/points?type=stats | GET | 获取用户综合统计(积分/评论/话题/评价数) |
|
||||
| /api/user/points?type=history | GET | 获取积分历史(分页) |
|
||||
|
||||
---
|
||||
|
||||
## 🆕 组件
|
||||
|
||||
### 论坛组件
|
||||
| 组件 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| ForumBoard | `src/components/forum/ForumBoard.tsx` | 论坛板块卡片(图标/名称/话题数) |
|
||||
| ForumTopicCard | `src/components/forum/ForumTopicCard.tsx` | 话题卡片(作者/时间/回复数/浏览数/等级徽章) |
|
||||
| ForumEditor | `src/components/forum/ForumEditor.tsx` | 论坛编辑器(字数限制/登录检查/错误提示) |
|
||||
| NotificationBell | `src/components/forum/NotificationBell.tsx` | 通知铃铛(红点/下拉面板/未读数) |
|
||||
|
||||
### 会员组件
|
||||
| 组件 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| MemberBadge | `src/components/common/MemberBadge.tsx` | 会员等级徽章(⭐🌟 + 积分显示,3种尺寸) |
|
||||
| LevelProgress | `src/components/common/LevelProgress.tsx` | 等级进度条(当前/下一级/进度百分比/最高级提示,动态变色) |
|
||||
| ShareButton | `src/components/common/ShareButton.tsx` | 分享按钮(支持原生分享/Twitter/QQ/复制链接,带成功反馈) |
|
||||
|
||||
### 评论组件
|
||||
| 组件 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| CommentCard | `src/components/common/CommentCard.tsx` | 评论卡片(用户信息/等级徽章/评分/点赞/回复/时间) |
|
||||
| CommentThread | `src/components/common/CommentThread.tsx` | 评论列表(分页/点赞/嵌套回复/排序) |
|
||||
|
||||
---
|
||||
|
||||
## 🆕 页面
|
||||
|
||||
### /community (追光会 - 论坛首页)
|
||||
- 板块网格(8个分类卡片)
|
||||
- 最新话题列表(排序/分页)
|
||||
- 活跃用户侧边栏
|
||||
|
||||
### /community/[category] (板块页面)
|
||||
- 话题列表(按板块筛选)
|
||||
- 排序切换(最新/热门/活跃)
|
||||
- 分页导航
|
||||
|
||||
### /community/topic/[id] (话题详情)
|
||||
- 话题完整内容展示
|
||||
- 回复列表(作者标记)
|
||||
- 回复表单(已登录可用)
|
||||
- 锁定话题显示提示
|
||||
|
||||
### /user (🆕 更新的用户中心)
|
||||
- 个人简介bio展示与编辑 🆕
|
||||
- 积分等级进度条
|
||||
- 积分明细记录
|
||||
- 统计卡片(评论数/话题数/评价数/积分)
|
||||
- 会员等级徽章
|
||||
- 快捷入口(收藏/浏览工具/浏览技能)
|
||||
- 最近浏览历史
|
||||
|
||||
### /user/[id] (🆕 会员个人空间)
|
||||
- 用户资料展示(头像/昵称/简介/等级/积分)
|
||||
- 统计面板(评论/话题/评价/积分)
|
||||
- 发布的主题列表
|
||||
- 评论历史列表
|
||||
- 分享按钮(支持原生分享/Twitter/QQ/复制链接)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术实现要点
|
||||
|
||||
### 积分自动奖励机制
|
||||
所有评论/发帖/点赞操作自动通过 `rewardPoints()` 发放积分,包含:
|
||||
- 每日上限检查(防刷分)
|
||||
- 事务写入(积分变更 + 历史记录同时写入)
|
||||
- 等级自动随积分变化更新
|
||||
|
||||
### 通知自动触发
|
||||
以下操作自动生成通知:
|
||||
- 回复评论 → 通知评论作者
|
||||
- 点赞评论 → 通知评论作者
|
||||
- 回复话题 → 通知话题作者
|
||||
|
||||
### 权限控制
|
||||
- 所有写操作(评论/发帖/回复/点赞)需已登录
|
||||
- 编辑/删除操作仅限作者本人
|
||||
- 锁定话题禁止回复
|
||||
@@ -0,0 +1,132 @@
|
||||
# 运维与部署模块
|
||||
|
||||
## 服务器与基础设施
|
||||
|
||||
### 环境信息
|
||||
- **域名**: www.zhuig.com (HTTPS,SSL证书自动续期)
|
||||
- **云服务器**: 119.45.242.239 (登录名: ubuntu, 密钥: E:\ZG_Dev\pem\zg.pem)
|
||||
- **数据库**: 阿里云RDS MySQL — rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306
|
||||
- **Redis**: Docker容器redis-cache:6379,有密码认证
|
||||
- **开发机**: E:\ZG_Dev\ZhuiGuangAI\zhuiguang-ai
|
||||
- **部署目录**: /home/ubuntu/zhuiguang-ai
|
||||
- **访问地址**: https://www.zhuig.com (HTTP自动跳转HTTPS)
|
||||
- **本地Git同步目录**: K:\git-repos
|
||||
|
||||
### 端口规范
|
||||
- **应用端口范围**: 8301-8310(预留扩展)
|
||||
- **默认端口**: 8301
|
||||
- **重启脚本**: 仅扫描8301-8310范围
|
||||
- **强制要求**: 本项目端口必须锁定在8301-8310区间内,禁止使用其他端口
|
||||
|
||||
## Nginx配置
|
||||
- 文件: `nginx.conf`
|
||||
- HTTPS反向代理到本地8301端口
|
||||
- HTTP自动跳转HTTPS
|
||||
- SSL证书自动续期
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 本地开发
|
||||
```bash
|
||||
# 1. 安装依赖
|
||||
npm install
|
||||
|
||||
# 2. 配置环境变量
|
||||
# 编辑 .env 文件
|
||||
|
||||
# 3. 数据库迁移
|
||||
npx prisma migrate dev
|
||||
|
||||
# 4. 启动开发服务器
|
||||
npm run dev
|
||||
# 或重启
|
||||
pwsh -ExecutionPolicy Bypass -File restart.ps1
|
||||
```
|
||||
|
||||
### 服务器部署
|
||||
```bash
|
||||
# 1. SSH到服务器
|
||||
ssh -i E:\ZG_Dev\pem\zg.pem ubuntu@119.45.242.239
|
||||
|
||||
# 2. 进入部署目录
|
||||
cd /home/ubuntu/zhuiguang-ai
|
||||
|
||||
# 3. 拉取最新代码
|
||||
git pull
|
||||
|
||||
# 4. 安装依赖
|
||||
npm install
|
||||
|
||||
# 5. 数据库迁移
|
||||
npx prisma migrate deploy
|
||||
|
||||
# 6. 构建生产版本
|
||||
npm run build
|
||||
|
||||
# 7. 重启服务
|
||||
pm2 restart zhuiguang-ai
|
||||
```
|
||||
|
||||
## 定时任务 (Crontab)
|
||||
|
||||
### Crontab配置
|
||||
- 用户: ubuntu
|
||||
- 查看: `crontab -l`
|
||||
- 编辑: `crontab -e`
|
||||
|
||||
### 任务列表
|
||||
|
||||
| 时间 | 任务 | 脚本 | TaskKey | 说明 |
|
||||
|------|------|------|---------|------|
|
||||
| 01:00 | Task5 更新星值 | `scripts/task5-update-stars.mjs` | task5-update-stars | 更新所有GitHub技能Stars数+日/周/月变化 |
|
||||
| 03:00 | Task3 工具巡检 | `scripts/task3-check-tools.mjs` | task3-check-tools | 检查网站/Logo可访问性+自动发布合格待审核工具 |
|
||||
| 04:00 | Task6 评测热门 | `scripts/task6-review-hot.mjs` | task6-review-hot | 评测2个最热未评测GitHub技能(五维评测) |
|
||||
| 05:00 | Task4 发现技能 | `scripts/daily-discover.mjs` | task4-discover-skills | GitHub搜索≥1000 stars项目→DeepSeek预评测→入库PendingSkill |
|
||||
| 06:00 | Task1 发现工具 | `scripts/task1-discover-tools.mjs` | task1-discover-tools | 36kr/IT之家/开源中国RSS→DeepSeek提取工具→入库PendingTool |
|
||||
| 07:30 | AI日报 | `scripts/daily-news.mjs` | daily-news | 多源搜索真实新闻+DeepSeek整理格式→发布日报 |
|
||||
|
||||
### 日志目录
|
||||
- 路径: `/home/ubuntu/zhuiguang-ai/logs/`
|
||||
- 文件: task1.log ~ task6.log
|
||||
|
||||
### 任务执行原理
|
||||
1. Crontab定时触发脚本执行
|
||||
2. 脚本调用外部API(GitHub/DeepSeek/网站)
|
||||
3. 数据写入数据库(Tool/Skill/PendingTool/PendingSkill/DailyReport)
|
||||
4. TaskLog表记录执行结果(status/duration/result/error)
|
||||
5. 后台管理页面可视化管理(/admin/tasks)
|
||||
6. 支持手动触发(POST /api/admin/tasks/run)
|
||||
|
||||
## 环境变量
|
||||
|
||||
### .env配置
|
||||
```bash
|
||||
# 数据库
|
||||
DATABASE_URL="mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai?charset=utf8mb4"
|
||||
|
||||
# NextAuth
|
||||
NEXTAUTH_URL="http://localhost:8301"
|
||||
NEXTAUTH_SECRET="zhuiguang-ai-dev-secret"
|
||||
|
||||
# GitHub API(可选,提升限流)
|
||||
GITHUB_TOKEN=""
|
||||
|
||||
# DeepSeek API(用于技能评测生成脚本、AI日报整理)
|
||||
DEEPSEEK_API_KEY="sk-..."
|
||||
```
|
||||
|
||||
## PM2配置
|
||||
- 进程名: zhuiguang-ai
|
||||
- 启动命令: `npm run start`
|
||||
- 端口: 8301
|
||||
- 重启: `pm2 restart zhuiguang-ai`
|
||||
|
||||
## 踩坑记录
|
||||
- Next.js 14不支持useActionState,登录页用原生表单POST
|
||||
- Prisma MariaDB adapter需要连接字符串方式初始化
|
||||
- 图片域名需在next.config.mjs中配置remotePatterns
|
||||
- 热重载后需清除.next缓存: 删除.next目录后重启
|
||||
- Chart.js组件需用dynamic import + ssr: false,不支持服务端渲染
|
||||
- Prisma 7.8需通过PrismaMariaDb适配器初始化,不能直接new PrismaClient()
|
||||
- 服务器环境SSL证书问题: 运行脚本需设置$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
|
||||
- Chart.js font.weight只接受bold/normal/bolder/lighter,不接受数字字符串如"500"
|
||||
Reference in New Issue
Block a user