v0.11.1: 权限体系重构 + AI管线优化 + 内容整理

This commit is contained in:
sgp
2026-05-22 18:36:41 +08:00
parent 7955d11c52
commit b33fe1e8e1
397 changed files with 30940 additions and 161 deletions
+15
View File
@@ -0,0 +1,15 @@
# Environment variables declared in this file are NOT automatically loaded by Prisma.
# Please add `import "dotenv/config";` to your `prisma.config.ts` file, or use the Prisma CLI with Bun
# to load environment variables from .env files: https://pris.ly/prisma-config-env-vars.
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="mysql://mohe001:Mohe168899%23@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai?charset=utf8mb4"
NEXTAUTH_URL="http://localhost:8301"
NEXTAUTH_SECRET="zhuiguang-ai-dev-secret"
GITHUB_TOKEN=""
DEEPSEEK_API_KEY="sk-91d1671855e44089b792b8147e17963f"
+2
View File
@@ -34,3 +34,5 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
/src/generated/prisma
+275
View File
@@ -0,0 +1,275 @@
# 追光AI 变更日志
## v0.11.1 (2026-05-22) - AI发现管线质量优化
### 全链路测试
- 跑通全部AI自动化管线:GitHub搜索 → DeepSeek评测 → 入库 → 内容生成
- 2个脚本(automatic-review + daily-discover) + 4个API端点全部验证通过
- 连测创建12条技能+评测记录,DeepSeek生成1篇日报+长文+视频脚本+社交卡片
### 质量过滤修复
- **非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
### JSON解析健壮性
- 新增 `extractJSON()` 统一工具函数 → `src/lib/utils.ts`
- 支持markdown代码块包裹(`\`\`\`json...\`\`\``)、花括号/方括号容错
- 替换 deepseek.ts、auto-review.mjs、daily-discover.mjs、daily-reports/generate 的旧解析逻辑
- 新增 `scripts/test-content-generation.mjs` 全管线测试脚本
### 新增脚本
- `scripts/cleanup-non-ai.mjs` — 一键清理误入库非AI技能数据
---
## v0.11.0 (2026-05-22) - 权限体系重构
### 架构变更
- **新增数据模型**: `Role`(角色), `Permission`(权限点), `RolePermission`(角色-权限关联) 三张表
- **User 模型**: 新增 `roleId` 字段关联 `Role`,与原有 `role` 字符串字段并行(向后兼容)
- 默认角色:**超级管理员**(Admin, 全部53权限)、**VIP成员**(Vip, 19个精选权限)
### 权限体系
- **53个精细化权限点**,按页面分组管理:
- 工具管理 14项 · 技能库 12项 · 评测管理 8项
- AI发现 7项 · 内容管理 8项 · 系统管理 4项
- 所有后台按钮/操作均已对应权限点,可逐个勾选控制
### 新增页面
- **`/admin/roles` 角色权限管理**: 左侧角色列表 + 右侧按分组的权限勾选网格
- 新建/删除自定义角色(系统角色受保护)
- 分组全选/取消全选
- 保存按钮实时同步到数据库
### 新增 API
- `GET/POST /api/admin/roles` — 角色列表/创建
- `PUT/DELETE /api/admin/roles/[id]` — 角色编辑/删除
- `GET /api/admin/permissions` — 全部权限点列表
- `GET /api/admin/user-permissions` — 用户权限查询(支持roleId/userId/当前用户)
### 鉴权升级
- **middleware.ts**: 从硬编码 `role==="admin"` 改为认证检查 + 路由层委派
- **admin-auth.ts**: `requireAdmin()` 兼容旧 `role` 字符串 + 新 `roleId` 关联角色双重逻辑
- 新增 `requirePermission(key)` — 细粒度权限点校验
- 新增 `getAllUserPermissions()` — 获取当前用户全部权限集合
### 前端工具
- 新增 `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]
### 修复
- 修复webpack缓存损坏导致的页面加载失败(清除.next目录)
- 修复左侧导航栏sticky定位不生效(flex容器添加self-start)
- 修复Logo被左侧导航遮挡(统一容器宽度)
---
## 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布局组件
+126
View File
@@ -0,0 +1,126 @@
# 追光AI 项目开发规则
## 端口规范
- 开发端口: 8301-8310
- 默认端口: 8301
- 重启脚本仅扫描8301-8310范围
- **强制要求:本项目端口必须锁定在8301-8310区间内,禁止使用其他端口,因为本服务器同时运行其他产品**
## 技术栈
- Next.js 14 (App Router) + TypeScript
- Tailwind CSS + shadcn/ui
- Prisma 7.8 + MySQL (阿里云RDS)
- NextAuth.js v4 (Credentials Provider)
- DeepSeek API (deepseek-v4-pro) — 用于技能五维评测生成(服务端脚本调用)
## 代码风格
- 不添加注释(除非明确要求)
- 使用中文作为UI文案和提示词语言
- TypeScript严格模式,零编译错误
- 组件使用 `"use client"` 标记客户端组件
- 路径别名: `@/*` → `./src/*`
- **禁止在代码中硬编码任何AI API Key**
- **禁止在代码中调用任何外部AI API(DeepSeek、OpenAI等)** — 前台/后台页面代码中禁止调用;服务端脚本(scripts/)中允许通过环境变量调用DeepSeek API和GitHub API
- 所有发现/导入功能通过页面提示词+JSON粘贴方式完成,不调用外部接口
## 构建与检查
- 修改代码后必须运行 `npx tsc --noEmit` 确认零错误
- 重启服务使用 `pwsh -ExecutionPolicy Bypass -File restart.ps1`
- 开发服务器: `npm run dev` (端口8301)
## 数据库
- 云数据库: 阿里云RDS MySQL
- 连接: `mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai`
- Prisma单例模式防止热重载多实例
- 修改Schema后: `npx prisma migrate dev --name <描述>`
## 认证
- 管理员: admin@zhuiguang.ai / admin123
- JWT Session策略
- middleware.ts保护/admin路由(跳过/admin/login)
- 后台API需requireAdmin中间件验证(src/lib/admin-auth.ts)
- 用户注册/登录: NextAuth Credentials Provider,支持邮箱+密码
## API约定
- 前台API: `/api/` 前缀,无需认证
- 后台API: `/api/admin/` 前缀,需NextAuth认证
- 分页参数: `page`(默认1), `pageSize`(默认20)
- 返回格式: `{ data, total, page, pageSize }` 或 `{ success, error }`
- 批量操作: 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`
## 五大操作指令
用户使用以下五个命令时,必须跳转到对应页面理解流程并按流程执行。
所有页面均为"提示词+JSON粘贴导入"模式,不调用任何外部AI API。
### 探索AI工具
- 页面: `/admin/discover-tools`
- 流程: 选分类 → 复制提示词发给AI → 粘贴JSON → 导入审核列表 → 抓取Logo
- 导入API: POST `/api/admin/discover-tools` body: `{ tools: [...], categoryId }`
- API接收前端提交的工具JSON数组,自动去重导入待审核列表
- Logo抓取API: POST `/api/admin/pending/fetch-logos`
- 工具分类(20个): 文本生成(165), 图像生成(174), 视频生成(183), 音频与语音(191), 代码开发(199), AI Agent(208), 办公效率(216), 设计与创意(224), 营销与SEO(231), 数据分析(238), 教育与学习(245), 搜索与信息(252), 安全与合规(258), 医疗健康(264), 金融与法律(270), 电商与零售(276), 3D与游戏(282), 科学研究(288), 模型与框架(294), 聊天机器人(302)
### 检测AI工具
- 页面: `/admin/check-tools`
- 流程: 选择范围(已发布/待审核) → 一键检测+抓取Logo → 处理失效工具
- 检测API: POST `/api/admin/check-tools` body: `{ type: "published" | "pending" }`
- 系统自动逐一GET请求检测网站可访问性,同时自动抓取缺失Logo并记录成功方法名
- 删除API: DELETE `/api/admin/tools/{id}` / `/api/admin/pending/{id}`
### 探索AI技能
- 页面: `/admin/discover-skills`
- 流程: 选分类 → 复制提示词发给AI → 粘贴JSON → 导入审核列表
- 导入API: POST `/api/admin/discover-skills` body: `{ skills: [...], categoryId }`
- API接收前端提交的技能JSON数组,自动去重导入待审核列表
- 技能分类(20个父分类): 代码生成(1), 测试(10), 代码质量与分析(20), 安全(29), 文档(36), 架构与设计(43), 需求工程(49), DevOps与部署(56), 调试与错误处理(62), 形式化验证(69), 维护与重构(76), 版本控制与协作(82), 开发工具(86), UI/UX设计(91), 科学研究(95), 金融(103), 云服务(109), 移动开发(115), AI/ML工程(120), 营销与增长(127)
### 更新Skill技能
- 页面: `/admin/update-skills`
- 流程: 选择范围(已发布/待审核) → 一键更新 → 自动同步星级
- 更新API: POST `/api/admin/update-stars` body: `{ type: "published" | "pending" }`
- 系统自动从GitHub/Gitee/GitCode API获取最新星级评分并写入数据库
### AI新闻发现
- 页面: `/admin/discover-news`
- 流程: 复制提示词发给AI → 粘贴JSON → 导入今日新闻
- 导入API: POST `/api/admin/discover-news` body: `{ items: [...] }`
- API接收前端提交的新闻JSON数组,自动生成今日AI日报
- 新闻分类: 产品发布/融资投资/技术突破/政策法规/开源项目/行业事件
### 通用执行规则
1. **禁止调用任何外部AI API**,所有发现/导入功能通过页面提示词+JSON粘贴方式完成
2. 页面提供提示词模板(含排除列表),用户复制发给AI助手获取JSON,粘贴到页面导入
3. 导入API接收JSON数组,自动去重(名称+网址),导入待审核列表
4. 导入工具后建议执行Logo抓取,确保所有工具有图标
5. 所有提示词要求: 优先推荐国产AI工具/技能,国内可直连,中文友好
6. 检测工具时:系统自动GET请求检测网站可访问性,同时抓取缺失Logo
7. 更新技能时:系统自动从GitHub/Gitee/GitCode API获取最新星级
## 设计系统
- 浅色主题,HSL CSS变量
- 圆角: rounded-xl / rounded-2xl
- 边框: border-border/40 (40%透明度)
- 背景: bg-white/80 (毛玻璃) / bg-white/60 (卡片) / bg-muted/50 (输入框)
- 阴影: shadow-sm (卡片) / shadow-md (悬浮)
- 动画: transition-all duration-200
- 自定义工具类: .glow-sm, .gradient-text, .glass, .card-shine, .dot-grid, .animate-fade-in
- 颜色规范: 文字用 -600/-700 (非-400),背景用 -50 (非-500/10),边框用 -200/60 (非-500/20)
- 输入框: bg-muted/50 focus:bg-white focus:ring-2 focus:ring-primary/10
## 环境变量
- GITHUB_TOKEN: GitHub Personal Access Token(可选,提升API限流从60→5000次/小时)
- DEEPSEEK_API_KEY: DeepSeek API Key(用于技能评测生成脚本)
## 踩坑记录
- 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"
+90
View File
@@ -0,0 +1,90 @@
# 追光AI - 模块文档索引
## 项目概述
追光AI是一个AI工具与开源技能目录网站,支持提示词驱动的工具/技能发现、审核管理和前台展示。
## 技术栈
| 类别 | 技术 | 版本 |
|------|------|------|
| 框架 | Next.js (App Router) | 14.2.35 |
| 语言 | TypeScript | 5.x |
| 样式 | Tailwind CSS + shadcn/ui | 3.x |
| 数据库 | MySQL (阿里云RDS) + Prisma | 7.8 |
| 认证 | NextAuth.js | v4 |
| AI | DeepSeek API (技能评测生成) | deepseek-v4-pro |
| 图表 | Chart.js + react-chartjs-2 | 4.x |
| 部署 | Node.js | 18+ |
| 端口 | 8301-8310 | 默认8301 |
## 项目结构
```
zhuiguang-ai/
├── prisma/ # 数据库Schema + 迁移 + 种子
├── public/ # 静态资源 (logo.png, logos/)
├── scripts/ # 独立脚本 (discover-skills, import-tools)
├── src/
│ ├── app/
│ │ ├── (admin)/admin/ # 后台页面 (15个页面)
│ │ ├── api/ # API路由 (36+个端点)
│ │ ├── categories/ # 前台分类页
│ │ ├── skills/ # 前台技能页
│ │ ├── tools/ # 前台工具页
│ │ ├── login/ # 用户登录页
│ │ ├── 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 # 依赖配置
```
## 模块文档
| 序号 | 模块 | 文档 | 说明 |
|------|------|------|------|
| 01 | 数据库 | [01-database.md](./modules/01-database.md) | 数据模型、枚举、索引、迁移历史 |
| 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) | 工具函数、独立脚本、运维脚本 |
## 环境变量
```
DATABASE_URL=mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai
NEXTAUTH_URL=http://localhost:8301
NEXTAUTH_SECRET=<secret>
GITHUB_TOKEN=<optional>
DEEPSEEK_API_KEY=<required-for-review>
```
## 核心业务流程
```
提示词模板(页面内嵌) → 用户复制发给AI助手 → AI返回JSON → 粘贴到页面导入
→ PendingTool / PendingSkill (待审核)
→ 管理员审核(编辑/发布/拒绝/批量操作)
→ Tool / Skill (已发布)
→ 前台展示(分类浏览/搜索/详情)
```
## 关键特性
- **提示词驱动**: 页面内嵌提示词模板(含排除列表),用户复制发给AI获取JSON后粘贴导入,不调用外部AI API
- **Logo自动抓取**: 10种策略按优先级执行,fetchLogoWithMethod返回成功方法名,支持20+常见路径和5个Favicon服务
- **检测+Logo联动**: 检测AI工具时同步抓取缺失Logo,记录每种抓取方法的成功次数统计
- **双轨内容**: 工具(Tool)面向商业AI产品,技能(Skill)面向GitHub开源项目
- **批量操作**: 批量导入、批量发布、批量拒绝、一键全部通过
- **GitHub Star同步**: 通过GitHub API定期更新技能Star数
- **AI新闻发现**: 提示词驱动发现AI新闻,按日生成日报,6大分类+热度评分
- **五维评测系统**: GitHub数据采集 + DeepSeek AI评测 + 雷达图展示,5维度(capability/devExp/costLicense/community/performance)评分
- **分页**: 所有列表页面支持分页(每页20条)
- **浅色主题**: 科技感浅色设计系统,毛玻璃效果+渐变文字+精致阴影
- **层级分类**: 一级分类+二级分类,左侧导航+标签切换
- **用户系统**: 邮箱注册/登录、收藏功能、浏览历史
- **安全加固**: 28个后台API全部添加requireAdmin中间件验证
- **端口锁定**: 8301-8310区间,禁止使用其他端口
+136
View File
@@ -0,0 +1,136 @@
# 数据库模块
## 技术栈
- Prisma 7.8 + @prisma/adapter-mariadb
- MySQL (阿里云RDS)
- 连接字符串: `mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai`
## 数据模型
### Category (工具分类)
| 字段 | 类型 | 说明 |
|------|------|------|
| 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 | 更新时间 |
### 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 | 更新时间 |
### Tool (已发布工具)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Int @id | 主键 |
| name | String | 工具名称 |
| slug | String @unique | URL标识 |
| categoryId | Int | 分类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) | 浏览次数 |
| status | Status @default(draft) | 状态(draft/published) |
| createdAt/updatedAt | DateTime | 时间戳 |
### PendingTool (待审核工具)
与Tool类似,但categoryId/description/websiteUrl等可为空,额外有sourceUrl和status(pending/approved/rejected)。
### Skill (已发布技能)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Int @id | 主键 |
| name | String | 技能名称 |
| slug | String @unique | URL标识 |
| categoryId | Int | 分类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) |
| tags | Json? | 标签数组 |
| viewCount | Int @default(0) | 浏览次数 |
| status | Status | 状态 |
| lastReviewedAt | DateTime? | 最近评测时间 |
| githubStarsHistory | Json? | Star历史数据 |
### PendingSkill (待审核技能)
与Skill类似,但多个字段可为空。
### SystemConfig (系统配置)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Int @id | 主键 |
| key | String @unique | 配置键 |
| value | Json | 配置值(JSON) |
### SkillReview (技能评测)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Int @id @default(autoincrement()) | 主键 |
| skillId | Int @unique | 关联Skill(一对一) |
| capability | Float | 场景与能力评分(1-5) |
| devExp | Float | 开发体验评分(1-5) |
| costLicense | Float | 成本与许可评分(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? | 社交卡片数据 |
| status | ReviewStatus @default(DRAFT) | 评测状态 |
| reviewedAt | DateTime @updatedAt | 评测时间 |
| createdAt | DateTime | 创建时间 |
### ReviewGenerationLog (评测生成日志)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Int @id @default(autoincrement()) | 主键 |
| skillId | Int | 关联Skill ID |
| status | String @db.VarChar(20) | SUCCESS/FAILED |
| prompt | String @db.Text | 生成提示词 |
| response | String? @db.Text | API响应内容 |
| error | String? @db.Text | 错误信息 |
| createdAt | DateTime | 创建时间 |
## 枚举
- `PricingModel`: free, freemium, paid, subscription
- `Status`: draft, published
- `PendingStatus`: pending, approved, rejected
- `ReviewStatus`: DRAFT, PUBLISHED, REJECTED, OUTDATED
## 索引
- Tool: categoryId+status联合索引, name+description全文索引
- Skill: categoryId+status联合索引
- SkillReview: skillId索引(唯一), overall索引
- ReviewGenerationLog: skillId索引
## 迁移历史
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字段
+140
View File
@@ -0,0 +1,140 @@
# API模块
## 前台API(无需认证)
### GET /api/homepage
获取首页数据(含嵌套分类结构,一级分类+二级子分类)。
- 返回: `{ categories: CategoryWithChildren[], skillCategories: SkillCategoryWithChildren[] }`
### GET /api/categories
获取工具分类树形结构(含子分类),按sortOrder排序。
### GET /api/skill-categories
获取技能分类树形结构(含子分类),按sortOrder排序。
### GET /api/tools
获取已发布工具列表。
- Query: `categoryId`, `pricingModel`, `search`, `page`(默认1), `pageSize`(默认20)
- 返回: `{ tools: Tool[], total, page, pageSize }`
### GET /api/tools/[slug]
获取工具详情(by slug),浏览计数+1。
### GET /api/skills
获取已发布技能列表。
- Query: `category`, `search`, `page`, `pageSize`
- 返回: `{ skills: Skill[], total, page, pageSize }`
### GET /api/skills/[slug]
获取技能详情(by slug),浏览计数+1。
### GET /api/skills/[slug]/review
获取技能的五维评测数据(仅返回PUBLISHED状态)。
- 返回: `{ capability, devExp, costLicense, community, performance, overall, reviews, longArticle?, videoScript?, socialCards?, reviewedAt }`
### GET/POST /api/auth/[...nextauth]
NextAuth认证端点(登录/回调/CSRF等)。
### 用户相关API(需NextAuth用户认证)
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/user/favorites | GET | 获取当前用户收藏列表(工具+技能) |
| /api/user/favorites | POST | 添加收藏(body: { targetType, targetId }) |
| /api/user/favorites | DELETE | 取消收藏(body: { targetType, targetId }) |
| /api/user/history | GET | 获取浏览历史 |
---
## 后台API(需NextAuth认证)
### 分类管理
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/admin/categories | GET | 获取所有分类(含工具数/子分类数) |
| /api/admin/categories | POST | 创建分类 |
| /api/admin/categories/[id] | PUT | 更新分类 |
| /api/admin/categories/[id] | DELETE | 删除分类(有工具/子分类时拒绝) |
| /api/admin/skill-categories | GET | 获取技能分类列表 |
| /api/admin/skill-categories | POST | 创建技能分类 |
| /api/admin/skill-categories/[id] | PUT | 更新技能分类 |
| /api/admin/skill-categories/[id] | DELETE | 删除技能分类 |
### 工具管理
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/admin/tools | GET | 获取所有工具(分页) |
| /api/admin/tools | POST | 创建工具 |
| /api/admin/tools/[id] | PUT | 更新工具 |
| /api/admin/tools/[id] | DELETE | 删除工具 |
### 技能管理
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/admin/skills | GET | 获取所有技能(分页) |
| /api/admin/skills/[id] | PUT | 更新技能 |
| /api/admin/skills/[id] | DELETE | 删除技能 |
### 待审核工具
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/admin/pending | GET | 获取待审核工具列表(分页) |
| /api/admin/pending | DELETE | 清空所有待审核工具 |
| /api/admin/pending/[id] | PUT | 编辑待审核工具(websiteUrl变更时自动抓Logo) |
| /api/admin/pending/[id] | DELETE | 删除单个待审核工具 |
| /api/admin/pending/[id]/publish | POST | 发布为正式工具 |
| /api/admin/pending/batch | POST | 批量导入(去重+自动抓Logo) |
| /api/admin/pending/batch-publish | POST | 批量发布(ids数组) |
| /api/admin/pending/batch-reject | POST | 批量拒绝(ids数组) |
| /api/admin/pending/fetch-logos | POST | 批量抓取Logo(body: {scope, refetch?}) |
### 待审核技能
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/admin/pending-skills | GET | 获取待审核技能列表(分页) |
| /api/admin/pending-skills | DELETE | 清空所有待审核技能 |
| /api/admin/pending-skills/[id] | PUT | 编辑待审核技能 |
| /api/admin/pending-skills/[id] | DELETE | 删除单个待审核技能 |
| /api/admin/pending-skills/[id]/publish | POST | 发布为正式技能 |
| /api/admin/pending-skills/batch | POST | 批量导入(去重) |
| /api/admin/pending-skills/batch-publish | POST | 批量发布(ids数组) |
| /api/admin/pending-skills/batch-reject | POST | 批量拒绝(ids数组) |
| /api/admin/pending-skills/publish-all | POST | 一键发布所有待审核技能 |
### AI发现与检测(提示词+JSON粘贴模式,不调用外部AI API)
| 路由 | 方法 | 功能 |
|------|------|------|
| /api/admin/discover-tools | POST | 导入工具JSON数组(body: {tools: [...], categoryId}),自动去重导入待审核列表 |
| /api/admin/discover-skills | POST | 导入技能JSON数组(body: {skills: [...], categoryId}),自动去重导入待审核列表 |
| /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/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? }) |
## SystemConfig 配置键
| Key | 类型 | 说明 |
|-----|------|------|
| discoveryPromptConfig | JSON | AI发现提示词配置(含toolPrompt/skillPrompt/newsPrompt/tagPool等) |
| logoFetchConfig | JSON | Logo抓取策略配置 |
| discoverSkillsScript | string | 技能探索脚本源码 |
+137
View File
@@ -0,0 +1,137 @@
# 页面模块
## 前台页面
### / (首页)
- 文件: `src/app/page.tsx`
- 功能: 搜索框、AI工具分类网格(一级+二级分类,左侧导航+标签切换)、技能分类网格、最新上架工具、热门工具、CTA区块
- 数据源: `/api/homepage`, `/api/categories`, `/api/skill-categories`, `/api/tools`
### /tools (工具列表)
- 文件: `src/app/tools/page.tsx`
- 功能: 分类筛选侧边栏(一级分类)、定价模型筛选、搜索、分页
- 数据源: `/api/categories`, `/api/tools`
### /tools/[slug] (工具详情)
- 文件: `src/app/tools/[slug]/page.tsx`
- 功能: 工具完整信息展示、浏览计数+1、收藏按钮、评论评价
- 数据源: `/api/tools/[slug]`
### /categories/[slug] (分类详情)
- 文件: `src/app/categories/[slug]/page.tsx`
- 功能: 按分类slug展示该分类下的工具
- 数据源: `/api/categories`, `/api/tools`
### /skills (技能库)
- 文件: `src/app/skills/page.tsx`
- 功能: 技能分类筛选(一级+二级分类,左侧导航+标签切换)、搜索
- 数据源: `/api/skill-categories`, `/api/skills`
### /skills/[slug] (技能详情)
- 文件: `src/app/skills/[slug]/page.tsx`
- 功能: 技能完整信息展示、浏览计数+1、收藏按钮、五维评测雷达图(SkillReviewCard)、评论评价
- 数据源: `/api/skills/[slug]`, `/api/skills/[slug]/review`
### /login (用户登录)
- 文件: `src/app/login/page.tsx`
- 功能: 用户邮箱+密码登录/注册,GitHub OAuth登录
- 数据源: NextAuth Credentials Provider
### /user (用户中心)
- 文件: `src/app/user/page.tsx`
- 功能: 用户资料编辑、快捷入口、浏览历史
- 数据源: NextAuth session, `/api/user/history`
### /user/favorites (我的收藏)
- 文件: `src/app/user/favorites/page.tsx`
- 功能: 收藏的工具和技能列表,支持筛选和搜索
- 数据源: `/api/user/favorites`
---
## 后台页面
### /admin/login (登录)
- 文件: `src/app/(admin)/admin/login/page.tsx`
- 功能: 管理员登录表单,CSRF token + 原生POST
- 凭证: admin@zhuiguang.ai / admin123
### /admin/pending (待审核工具)
- 文件: `src/app/(admin)/admin/pending/page.tsx`
- 功能: 审核列表表格、多选复选框、全选、批量通过/拒绝、抓取缺失Logo/重新抓取全部Logo、编辑弹窗、单个通过/拒绝
- 数据源: `/api/admin/pending`, `/api/admin/pending/batch-publish`, `/api/admin/pending/batch-reject`, `/api/admin/pending/fetch-logos`
### /admin/pending-skills (待审核技能)
- 文件: `src/app/(admin)/admin/pending-skills/page.tsx`
- 功能: 审核列表表格、多选复选框、全选、批量通过/拒绝、一键全部通过、编辑弹窗、Star数展示、GitHub链接
- 数据源: `/api/admin/pending-skills`, `/api/admin/pending-skills/batch-publish`, `/api/admin/pending-skills/batch-reject`, `/api/admin/pending-skills/publish-all`
### /admin/tools (已发布工具)
- 文件: `src/app/(admin)/admin/tools/page.tsx`
- 功能: 工具管理表格、新增/编辑/删除、分页
- 数据源: `/api/admin/tools`, `/api/admin/categories`
### /admin/skills (已发布技能)
- 文件: `src/app/(admin)/admin/skills/page.tsx`
- 功能: 技能管理表格、编辑/删除、分页
- 数据源: `/api/admin/skills`, `/api/admin/skill-categories`
### /admin/categories (工具分类管理)
- 文件: `src/app/(admin)/admin/categories/page.tsx`
- 功能: 分类CRUD、树形展示、排序
- 数据源: `/api/admin/categories`
### /admin/skill-categories (技能分类管理)
- 文件: `src/app/(admin)/admin/skill-categories/page.tsx`
- 功能: 技能分类CRUD
- 数据源: `/api/admin/skill-categories`
### /admin/discover-tools (探索AI工具)
- 文件: `src/app/(admin)/admin/discover-tools/page.tsx`
- 功能: 选分类→复制提示词→粘贴JSON→导入审核列表→抓取Logo
- 流程: 4步流程(选分类/复制提示词/粘贴导入/抓取Logo),提示词含排除列表,JSON粘贴区+导入按钮,Logo批量抓取
- 数据源: `/api/admin/discover-tools`, `/api/admin/pending/fetch-logos`
### /admin/check-tools (检测AI工具)
- 文件: `src/app/(admin)/admin/check-tools/page.tsx`
- 功能: 4步流程(选范围/检测+抓取/Logo方法统计/处理失效),检测可访问性同时自动抓取缺失Logo,记录成功方法名统计
- 数据源: `/api/admin/check-tools`, `/api/admin/tools/[id]`, `/api/admin/pending/[id]`
### /admin/discover-skills (探索AI技能)
- 文件: `src/app/(admin)/admin/discover-skills/page.tsx`
- 功能: 选分类→复制提示词→粘贴JSON→导入审核列表
- 流程: 3步流程(选分类/复制提示词/粘贴导入),提示词含排除列表,JSON粘贴区+导入按钮
- 数据源: `/api/admin/discover-skills`
### /admin/update-skills (更新Skill技能)
- 文件: `src/app/(admin)/admin/update-skills/page.tsx`
- 功能: 3步流程(选范围/一键更新/自动同步),更新GitHub/Gitee/GitCode星级,展示Star变化表格
- 数据源: `/api/admin/update-stars`
### /admin/discover-news (AI新闻发现)
- 文件: `src/app/(admin)/admin/discover-news/page.tsx`
- 功能: 3步流程(复制提示词/粘贴导入/查看日报),新闻6大分类+热度评分,展示今日AI日报
- 数据源: `/api/admin/discover-news`
### /admin/system-config (系统配置)
- 文件: `src/app/(admin)/admin/system-config/page.tsx`
- 功能: Logo抓取配置、发现提示词配置等全局设置
- 数据源: `/api/admin/system-config`
---
## 布局
### 前台布局
- 文件: `src/app/layout.tsx`
- 结构: Geist字体 → AuthProvider → Header + main + Footer
### 后台布局
- 文件: `src/app/(admin)/admin/layout.tsx`
- 结构: 左侧边栏(4组菜单) + 右侧内容区
- 菜单分组:
- 工具管理: 待审核工具、已发布工具、工具分类
- 技能库: 待审核技能、已发布技能、技能分类
- AI发现: 探索AI工具、检测AI工具、探索Skill技能、更新Skill技能、AI新闻发现
- 系统配置: 系统配置
- 登录页不显示侧边栏
@@ -0,0 +1,117 @@
# 组件与样式模块
## 组件
### 布局组件
#### Header (`src/components/layout/Header.tsx`)
- 前台顶部导航栏
- Logo + 导航链接(工具库/技能库/分类浏览) + 搜索框 + 登录/用户按钮
- 移动端汉堡菜单
- 滚动时背景模糊效果(bg-white/80 backdrop-blur-2xl)
- 搜索框: bg-muted/50 focus:bg-white focus:ring-2 focus:ring-primary/10
#### Footer (`src/components/layout/Footer.tsx`)
- 前台底部页脚
- Logo + 简介 + 发现/分类/关于链接 + 社交图标(GitHub/Twitter)
### Provider组件
#### AuthProvider (`src/components/providers/auth-provider.tsx`)
- NextAuth SessionProvider 包裹组件
- 用于在客户端组件中访问session
### 公共组件
#### LoginModal (`src/components/common/LoginModal.tsx`)
- 登录/注册弹窗,支持模式切换
- 邮箱+密码认证,注册可选填昵称
- bg-white/95 backdrop-blur-xl
#### SkillReviewCard (五维评测雷达图)
- 文件: `src/components/common/SkillReviewCard.tsx`
- 用途: 技能详情页展示五维评测雷达图和维度详情卡片
- 依赖: chart.js, react-chartjs-2 (dynamic import, ssr: false)
- Props: `{ slug: string }`
- 数据源: `/api/skills/${slug}/review`
- 五维度: 场景与能力(capability) / 开发体验(devExp) / 成本与许可(costLicense) / 社区健康(community) / 性能稳定(performance)
- 评分色标: ≥4绿色(emerald) / ≥3黄色(amber) / <3红色(red)
- 设计规范: 遵循浅色主题设计系统,紫色(violet)主色调雷达图
### ReviewSection (`src/components/common/ReviewSection.tsx`)
- 用户评论/评价组件,支持评分和文字评论
- 支持tool和skill两种类型
- bg-white/80卡片,bg-white/60评论项
#### FavoriteButton (`src/components/common/FavoriteButton.tsx`)
- 收藏按钮,乐观更新
- text-gray-500 hover:text-red-500
#### CategorySidebar (`src/components/common/CategorySidebar.tsx`)
- 分类侧边栏,支持搜索和分类选择
- bg-muted/50搜索框
### UI组件 (shadcn/ui)
#### Button (`src/components/ui/button.tsx`)
- 6种变体: default, outline, secondary, ghost, destructive, link
- 4种尺寸: default, sm, lg, icon
#### Card (`src/components/ui/card.tsx`)
- Card/CardHeader/CardTitle/CardDescription/CardContent/CardFooter
#### Dialog (`src/components/ui/dialog.tsx`)
- 基于 @radix-ui/react-dialog
- Dialog/DialogTrigger/DialogContent/DialogHeader/DialogTitle/DialogDescription/DialogFooter/DialogClose
- 遮罩层: bg-black/80
---
## 样式系统
### 全局样式 (`src/app/globals.css`)
- 浅色主题CSS变量(HSL色系)
- shadcn/ui 主题变量
- 自定义工具类:
- `.glow-sm` / `.glow-md` / `.glow-lg` - 发光效果
- `.gradient-text` - 渐变文字(蓝→紫→粉)
- `.gradient-border` - 渐变边框
- `.glass` / `.glass-sm` - 毛玻璃效果(bg-white/80 + backdrop-blur)
- `.card-shine` - 卡片光泽动画
- `.dot-grid` - 点阵网格背景
- `.animate-fade-in` - 淡入动画
- `.animate-slide-up` - 上滑动画
- `.animate-float` - 浮动动画
- `.animate-pulse-glow` - 脉冲发光
### Tailwind配置 (`tailwind.config.ts`)
- 浅色模式: class策略
- 主题色系: HSL CSS变量(background: 210 20% 98%, foreground: 222 47% 11%, primary: 221 83% 53%等)
- 动画: fade-in, slide-up, float, glow-pulse
- 自定义字体: Geist Sans, Geist Mono
### 设计规范
- 圆角: 统一使用 rounded-xl (12px) 或 rounded-2xl (16px)
- 边框: border-border/40 (40%透明度)
- 背景: bg-white/80 (毛玻璃) / bg-white/60 (卡片) / bg-muted/50 (输入框)
- 阴影: shadow-sm (卡片) / shadow-md (悬浮)
- 间距: 统一使用 Tailwind 间距系统
- 动画: transition-all duration-200
### 颜色规范(浅色主题)
- 文字颜色: 使用 -600/-700 系列(如 text-blue-700, text-emerald-600)
- 背景颜色: 使用 -50 系列(如 bg-blue-50, bg-emerald-50)
- 边框颜色: 使用 -200/60 系列(如 border-blue-200/60, border-emerald-200/60)
- 严禁使用暗色主题的 -400 文字、-500/10 背景、-500/20 边框
- 输入框: bg-muted/50 focus:bg-white focus:ring-2 focus:ring-primary/10
### 定价模型颜色
- free: bg-emerald-50 text-emerald-700 border-emerald-200/60
- freemium: bg-blue-50 text-blue-700 border-blue-200/60
- paid: bg-amber-50 text-amber-700 border-amber-200/60
- subscription: bg-purple-50 text-purple-700 border-purple-200/60
### 来源类型颜色
- github: bg-slate-50 text-slate-700
- gitlab: bg-orange-50 text-orange-700
- huggingface: bg-yellow-50 text-yellow-700
+132
View File
@@ -0,0 +1,132 @@
# AI发现模块
## 概述
AI发现模块是追光AI的核心功能,采用"提示词+JSON粘贴导入"模式,用户复制页面内嵌的提示词发给AI助手,获取JSON后粘贴到页面导入,不调用任何外部AI API。
## 架构
```
页面内嵌提示词模板(含排除列表) → 用户复制发给AI助手 → AI返回JSON → 粘贴到页面 → API去重导入 → PendingTool/PendingSkill → 管理员审核 → Tool/Skill
```
## 五大操作指令
### 探索AI工具 (`/admin/discover-tools`)
1. 选择分类(20个工具分类)
2. 复制提示词(自动注入排除列表)
3. 粘贴AI返回的JSON到输入框
4. 点击导入按钮,API自动去重导入待审核列表
5. 可选:批量抓取Logo
### 检测AI工具 (`/admin/check-tools`)
1. 选择范围(已发布/待审核)
2. 一键检测+抓取Logo
3. 系统自动逐一GET请求检测网站可访问性
4. 同时自动抓取缺失Logo,记录成功方法名
5. 展示Logo抓取方法统计(按成功次数排序)
6. 失效工具可一键删除
### 探索AI技能 (`/admin/discover-skills`)
1. 选择分类(20个技能分类)
2. 复制提示词(自动注入排除列表)
3. 粘贴AI返回的JSON到输入框
4. 点击导入按钮,API自动去重导入待审核列表
### 更新Skill技能 (`/admin/update-skills`)
1. 选择范围(已发布/待审核)
2. 一键更新Star
3. 系统自动从GitHub/Gitee/GitCode API获取最新星级
4. 展示Star变化表格(上升/下降/不变)
### AI新闻发现 (`/admin/discover-news`)
1. 复制新闻发现提示词
2. 粘贴AI返回的JSON到输入框
3. 点击导入按钮,自动生成今日AI日报
4. 新闻6大分类:产品发布/融资投资/技术突破/政策法规/开源项目/行业事件
5. 每条新闻含热度评分(1-100)
## Logo抓取引擎 (`src/lib/logo-fetcher.ts`)
### 核心API
- `fetchLogo(websiteUrl, html?): Promise<string>` — 返回Logo URL
- `fetchLogoWithMethod(websiteUrl, html?): Promise<{url, method}>` — 返回Logo URL + 成功方法名
### 抓取策略(按优先级,共10种)
1. **HTML Link图标**: 解析 `<link rel="icon/apple-touch-icon">` 标签
2. **OG/Twitter图片**: 解析 `<meta property="og:image">` 标签
3. **HTML Manifest**: 解析 `manifest.json` 中的icons数组
4. **HTML img标签**: 查找class/alt含"logo"的img标签
5. **Header区域Logo**: 解析header/nav区域内的img标签
6. **SVG Logo**: 查找内联SVG logo
7. **常见路径**: 尝试 /apple-touch-icon.png, /logo.png, /favicon.ico 等
8. **Favicon服务**:
- favicon.im
- Google Favicons (sz=128/64)
- Clearbit
- DuckDuckGo
- Favicon Grabr (API解析)
- Icon Horse (API解析)
9. **Brandfetch品牌库**: 通过Brandfetch API获取品牌Logo
10. **截图兜底**: 通过截图服务获取网站截图
### 配置项
- `enabledMethods`: 启用的抓取方法
- `commonPaths`: 常见图标路径列表
- `faviconServices`: Favicon服务列表
- `minFileSize`: 最小文件大小(默认50字节)
- `requestTimeout`: 请求超时(默认10秒)
### Logo本地存储 (`src/lib/logo-storage.ts`)
- `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` 批量导入
## 自动化评测流程
### 架构概览
```
GitHub API (octokit) → 搜索热门仓库 → 获取README
↓
DeepSeek API (openai兼容) → 五维评测生成 → JSON解析+校验
↓
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
### 五维评测维度
| 维度 | 字段 | 说明 |
|------|------|------|
| 场景与能力 | capability | 场景覆盖度和核心能力 |
| 开发体验 | devExp | 安装、文档、API易用性 |
| 成本与许可 | costLicense | 硬件成本、API定价、许可证风险 |
| 社区健康 | community | Issue响应、PR频率、生态 |
| 性能稳定 | performance | 运行效率、稳定性、输出质量 |
### 评测标签分类
LLM框架, Agent框架, RAG, 提示工程, 多模态, 代码助手, 模型训练, 数据工程, 部署工具, 评测工具, 安全对齐, 其他
### 发布评测脚本 (scripts/publish-reviews.mjs)
- 将DRAFT状态评测改为PUBLISHED
- 同时将对应Skill状态从draft改为published
## 踩坑记录
+58
View File
@@ -0,0 +1,58 @@
# 认证模块
## 技术栈
- NextAuth.js v4
- Credentials Provider(用户名密码 + 用户邮箱密码)
- JWT Session策略
## 配置 (`src/lib/auth.ts`)
### 管理员认证
- 唯一凭证: `admin@zhuiguang.ai` / `admin123`
- 硬编码在auth.ts中,非数据库查询
### 用户认证
- 邮箱+密码注册/登录
- 用户数据存储在User表
- 密码bcrypt加密
### Session策略
- 使用JWT,不使用数据库session
- JWT密钥: `NEXTAUTH_SECRET` 环境变量
### 回调函数
- `jwt`: 登录时将用户信息加入token
- `session`: 将token中的用户信息传递给session
## 路由保护 (`src/middleware.ts`)
### 保护规则
- 保护 `/admin` 下所有路由
- 跳过 `/admin/login`
- 使用NextAuth middleware进行认证检查
### 登录流程
1. 访问 `/admin/*` → middleware检查session
2. 未登录 → 重定向到 `/admin/login`
3. 登录页提交表单 → Server Action验证凭证
4. 验证成功 → 重定向到 `/admin`
## 管理员API认证 (`src/lib/admin-auth.ts`)
### requireAdmin中间件
- 所有 `/api/admin/` 路由必须使用requireAdmin中间件
- 验证流程: 检查session → 验证邮箱是否为admin@zhuiguang.ai
- 已覆盖28个后台API端点
## 登录页
- 管理员登录: `src/app/(admin)/admin/login/page.tsx` (原生HTML表单 + CSRF Token)
- 用户登录: `src/app/login/page.tsx` (NextAuth Credentials + GitHub OAuth)
- 用户登录弹窗: `src/components/common/LoginModal.tsx`
## 环境变量
```
NEXTAUTH_URL=http://localhost:3100
NEXTAUTH_SECRET=<secret>
GITHUB_ID=<github-oauth-id>
GITHUB_SECRET=<github-oauth-secret>
```
+110
View File
@@ -0,0 +1,110 @@
# 工具库与脚本模块
## 工具库 (`src/lib/`)
### src/lib/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`
---
## 脚本 (`scripts/`)
### discover-skills.mjs - AI技能发现
- 独立运行的Node.js脚本
- 遍历20个技能分类,每类调用DeepSeek API推荐10个GitHub开源项目
- 通过 `/api/admin/pending-skills/batch` 批量导入
- 自动排除已收录技能
- 每分类间隔3秒
- 运行: `node scripts/discover-skills.mjs`
### import-tools-batch1.mjs - 第一批工具导入
- 硬编码约80个国产AI工具
- 分类: 文本生成(165)/图像生成(174)/视频生成(183)/音频与语音(191)
### import-tools-batch2.mjs - 第二批工具导入
- 硬编码约200个国产AI工具
- 分类: 代码开发/AI Agent/办公效率/设计创意/营销SEO/数据分析/教育学习/搜索信息/安全合规/医疗健康/金融法律/电商零售/3D游戏/科学研究/模型框架/聊天机器人
---
## 运维脚本
### 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端口
- 杀死占用进程
- 执行 `npm run dev` 启动服务(端口8301)
- 运行: `pwsh -ExecutionPolicy Bypass -File restart.ps1`
### temp_clear.mjs - 临时清理
- 清空pending_tools表
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"代码生成"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"测试"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"代码质量与分析"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"安全"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"文档"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"架构与设计"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"需求工程"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"DevOps 与部署"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"调试与错误处理"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"形式化验证"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"维护与重构"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"版本控制与协作"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"开发工具"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"UI/UX 设计"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"科学研究"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"金融"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"云服务"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"移动开发"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"AI/ML 工程"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+20
View File
@@ -0,0 +1,20 @@
你是AI编程技能专家。请为"营销与增长"领域推荐 12 个真实存在且活跃的AI编程技能(Prompt/Agent/Workflow/开源项目)。
严格要求:
1. 优先推荐 Gitee(gitee.com)和 GitCode(gitcode.com)上的国内开源项目,也接受少量优秀的国际开源项目
2. 推荐的技能必须是真实可用的AI编程技能,可以是开源项目、Prompt模板、AI Agent配置或自动化工作流
3. sourceUrl必须是真实可访问的链接(Gitee仓库、GitCode仓库、GitHub仓库等)
4. 每个技能的name、sourceUrl必须唯一,不能与已有技能重复
5. 技能应该有实用价值,能直接用于编程开发场景
6. rating为该技能在来源平台上的用户评分(1.0-5.0分),如无评分则根据star数和活跃度估算
每个技能包含以下字段:
- name: 技能名称(简洁明了,如"React组件生成器"、"SQL注入检测Agent")
- description: 一句话中文简介(50字以内,突出核心能力和使用场景)
- sourceUrl: 来源链接(Gitee仓库URL、GitCode仓库URL或GitHub仓库URL,必须以http://或https://开头)
- sourceType: 来源类型,只能是以下之一:"gitee"、"gitcode"、"github"、"other"
- rating: 用户评分(1.0-5.0之间的浮点数,如4.5、3.8)
- features: 功能特性数组(3-5个关键特性,每个特性10字以内)
- tags: 标签数组(3-5个标签,从限定标签池中选取:代码生成、代码审查、自动化测试、安全检测、文档生成、DevOps、重构、调试、AI Agent、Prompt工程、RAG、MCP、前端开发、后端开发、移动开发、云原生、开源项目、中文优化、开箱即用、企业级)
返回纯JSON数组,不要包含任何其他文字、markdown标记或代码块标记。
+162
View File
@@ -0,0 +1,162 @@
[
{
"index": 1,
"categoryId": 1,
"categoryName": "代码生成",
"filename": "01_代码生成.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 2,
"categoryId": 10,
"categoryName": "测试",
"filename": "02_测试.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 3,
"categoryId": 20,
"categoryName": "代码质量与分析",
"filename": "03_代码质量与分析.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 4,
"categoryId": 29,
"categoryName": "安全",
"filename": "04_安全.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 5,
"categoryId": 36,
"categoryName": "文档",
"filename": "05_文档.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 6,
"categoryId": 43,
"categoryName": "架构与设计",
"filename": "06_架构与设计.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 7,
"categoryId": 49,
"categoryName": "需求工程",
"filename": "07_需求工程.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 8,
"categoryId": 56,
"categoryName": "DevOps 与部署",
"filename": "08_DevOps 与部署.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 9,
"categoryId": 62,
"categoryName": "调试与错误处理",
"filename": "09_调试与错误处理.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 10,
"categoryId": 69,
"categoryName": "形式化验证",
"filename": "10_形式化验证.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 11,
"categoryId": 76,
"categoryName": "维护与重构",
"filename": "11_维护与重构.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 12,
"categoryId": 82,
"categoryName": "版本控制与协作",
"filename": "12_版本控制与协作.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 13,
"categoryId": 86,
"categoryName": "开发工具",
"filename": "13_开发工具.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 14,
"categoryId": 91,
"categoryName": "UI/UX 设计",
"filename": "14_UI-UX 设计.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 15,
"categoryId": 95,
"categoryName": "科学研究",
"filename": "15_科学研究.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 16,
"categoryId": 103,
"categoryName": "金融",
"filename": "16_金融.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 17,
"categoryId": 109,
"categoryName": "云服务",
"filename": "17_云服务.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 18,
"categoryId": 115,
"categoryName": "移动开发",
"filename": "18_移动开发.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 19,
"categoryId": 120,
"categoryName": "AI/ML 工程",
"filename": "19_AI-ML 工程.txt",
"currentCount": 0,
"needCount": 10
},
{
"index": 20,
"categoryId": 127,
"categoryName": "营销与增长",
"filename": "20_营销与增长.txt",
"currentCount": 0,
"needCount": 10
}
]
+25
View File
@@ -0,0 +1,25 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
+75 -1
View File
@@ -1,4 +1,78 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "**",
},
],
minimumCacheTTL: 3600,
formats: ["image/avif", "image/webp"],
},
compress: true,
poweredByHeader: false,
reactStrictMode: true,
webpack: (config, { isServer }) => {
config.watchOptions = {
...config.watchOptions,
ignored: [
"**/node_modules/**",
"**/.git/**",
"**/System Volume Information/**",
"**/DumpStack.log.tmp",
"**/pagefile.sys",
],
poll: false,
};
return config;
},
onDemandEntries: {
maxInactiveAge: 60 * 1000,
pagesBufferLength: 5,
},
experimental: {
optimizeCss: false,
},
headers: async () => {
const isDev = process.env.NODE_ENV === "development";
const headers = [
{
source: "/api/:path*",
headers: [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "X-XSS-Protection", value: "1; mode=block" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
],
},
{
source: "/logos/:path*",
headers: [
{ key: "Cache-Control", value: isDev ? "no-cache" : "public, max-age=86400, immutable" },
],
},
];
if (isDev) {
headers.push({
source: "/(.*)",
headers: [
{ key: "Cache-Control", value: "no-store, no-cache, must-revalidate, proxy-revalidate" },
],
});
} else {
headers.push({
source: "/_next/static/:path*",
headers: [
{ key: "Cache-Control", value: "public, max-age=31536000, immutable" },
],
});
}
return headers;
},
};
export default nextConfig;
+6315 -41
View File
File diff suppressed because it is too large Load Diff
+30 -5
View File
@@ -3,22 +3,47 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbo --port 8301",
"build": "next build",
"start": "next start",
"start": "next start --port 8301",
"lint": "next lint"
},
"dependencies": {
"@base-ui/react": "^1.4.1",
"@prisma/adapter-mariadb": "^7.8.0",
"@prisma/client": "^7.8.0",
"@radix-ui/react-dialog": "^1.1.15",
"@types/bcryptjs": "^2.4.6",
"axios": "^1.15.2",
"bcryptjs": "^3.0.3",
"chart.js": "^4.5.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^1.11.0",
"next": "14.2.35",
"next-auth": "^4.24.14",
"octokit": "^5.0.5",
"openai": "^6.38.0",
"prisma": "^7.8.0",
"react": "^18",
"react-chartjs-2": "^5.3.1",
"react-dom": "^18",
"next": "14.2.35"
"shadcn": "^4.5.0",
"tailwind-merge": "^3.5.0",
"tw-animate-css": "^1.4.0"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"dotenv": "^17.4.2",
"mysql2": "^3.22.3",
"postcss": "^8",
"tailwindcss": "^3.4.1"
"tailwindcss": "^3.4.1",
"ts-node": "^10.9.2",
"typescript": "^5"
},
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
}
}
+15
View File
@@ -0,0 +1,15 @@
// This file was generated by Prisma, and assumes you have installed the following:
// npm install --save-dev prisma dotenv
import "dotenv/config";
import { defineConfig } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
seed: 'ts-node --compiler-options {"module":"CommonJS"} prisma/seed.ts',
},
datasource: {
url: process.env["DATABASE_URL"],
},
});
@@ -0,0 +1,66 @@
-- CreateTable
CREATE TABLE `categories` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`slug` VARCHAR(50) NOT NULL,
`icon` VARCHAR(100) NULL,
`parent_id` INTEGER NULL,
`sort_order` INTEGER NOT NULL DEFAULT 0,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `categories_slug_key`(`slug`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `tools` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) NOT NULL,
`category_id` INTEGER NOT NULL,
`description` TEXT NOT NULL,
`logo_url` VARCHAR(255) NULL,
`website_url` VARCHAR(255) NOT NULL,
`pricing_model` ENUM('free', 'freemium', 'paid', 'subscription') NOT NULL DEFAULT 'freemium',
`pricing_detail` VARCHAR(200) NULL,
`features` JSON NULL,
`tags` JSON NULL,
`view_count` INTEGER NOT NULL DEFAULT 0,
`status` ENUM('draft', 'published') NOT NULL DEFAULT 'draft',
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `tools_slug_key`(`slug`),
INDEX `tools_category_id_status_idx`(`category_id`, `status`),
FULLTEXT INDEX `tools_name_description_idx`(`name`, `description`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `pending_tools` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) NULL,
`category_id` INTEGER NULL,
`description` TEXT NULL,
`logo_url` VARCHAR(255) NULL,
`website_url` VARCHAR(255) NULL,
`pricing_model` ENUM('free', 'freemium', 'paid', 'subscription') NULL DEFAULT 'freemium',
`pricing_detail` VARCHAR(200) NULL,
`features` JSON NULL,
`tags` JSON NULL,
`source_url` VARCHAR(255) NULL,
`scraped_at` DATETIME(3) NULL,
`status` ENUM('pending', 'approved', 'rejected') NOT NULL DEFAULT 'pending',
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- AddForeignKey
ALTER TABLE `categories` ADD CONSTRAINT `categories_parent_id_fkey` FOREIGN KEY (`parent_id`) REFERENCES `categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `tools` ADD CONSTRAINT `tools_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
@@ -0,0 +1,8 @@
/*
Warnings:
- You are about to drop the column `scraped_at` on the `pending_tools` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE `pending_tools` DROP COLUMN `scraped_at`;
@@ -0,0 +1,13 @@
-- CreateTable
CREATE TABLE `discovery_configs` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`category_id` INTEGER NULL,
`prompt` TEXT NOT NULL,
`tagPool` JSON NULL,
`temperature` DOUBLE NOT NULL DEFAULT 0.7,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `discovery_configs_category_id_key`(`category_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
@@ -0,0 +1,9 @@
/*
Warnings:
- You are about to drop the column `tagPool` on the `discovery_configs` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE `discovery_configs` DROP COLUMN `tagPool`,
ADD COLUMN `tag_pool` JSON NULL;
@@ -0,0 +1,4 @@
-- AlterTable
ALTER TABLE `discovery_configs` ADD COLUMN `apiBaseUrl` VARCHAR(255) NULL,
ADD COLUMN `apiKey` VARCHAR(255) NULL,
ADD COLUMN `modelName` VARCHAR(100) NULL;
@@ -0,0 +1,71 @@
/*
Warnings:
- You are about to drop the column `apiBaseUrl` on the `discovery_configs` table. All the data in the column will be lost.
- You are about to drop the column `apiKey` on the `discovery_configs` table. All the data in the column will be lost.
- You are about to drop the column `modelName` on the `discovery_configs` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE `discovery_configs` DROP COLUMN `apiBaseUrl`,
DROP COLUMN `apiKey`,
DROP COLUMN `modelName`,
ADD COLUMN `api_provider_id` INTEGER NULL;
-- CreateTable
CREATE TABLE `skills` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) NOT NULL,
`category_id` INTEGER NOT NULL,
`description` TEXT NOT NULL,
`logo_url` VARCHAR(255) NULL,
`source_url` VARCHAR(255) NOT NULL,
`source_type` VARCHAR(20) NOT NULL DEFAULT 'github',
`features` JSON NULL,
`tags` JSON NULL,
`view_count` INTEGER NOT NULL DEFAULT 0,
`status` ENUM('draft', 'published') NOT NULL DEFAULT 'draft',
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `skills_slug_key`(`slug`),
INDEX `skills_category_id_status_idx`(`category_id`, `status`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `pending_skills` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) NULL,
`category_id` INTEGER NULL,
`description` TEXT NULL,
`logo_url` VARCHAR(255) NULL,
`source_url` VARCHAR(255) NULL,
`source_type` VARCHAR(20) NULL,
`features` JSON NULL,
`tags` JSON NULL,
`status` ENUM('pending', 'approved', 'rejected') NOT NULL DEFAULT 'pending',
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `api_providers` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`baseUrl` VARCHAR(255) NOT NULL,
`apiKey` VARCHAR(255) NOT NULL,
`model` VARCHAR(100) NOT NULL,
`isDefault` BOOLEAN NOT NULL DEFAULT false,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- AddForeignKey
ALTER TABLE `skills` ADD CONSTRAINT `skills_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
@@ -0,0 +1,23 @@
-- DropForeignKey
ALTER TABLE `skills` DROP FOREIGN KEY `skills_category_id_fkey`;
-- CreateTable
CREATE TABLE `skill_categories` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`slug` VARCHAR(50) NOT NULL,
`icon` VARCHAR(100) NULL,
`parent_id` INTEGER NULL,
`sort_order` INTEGER NOT NULL DEFAULT 0,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `skill_categories_slug_key`(`slug`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- AddForeignKey
ALTER TABLE `skill_categories` ADD CONSTRAINT `skill_categories_parent_id_fkey` FOREIGN KEY (`parent_id`) REFERENCES `skill_categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `skills` ADD CONSTRAINT `skills_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `skill_categories`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
@@ -0,0 +1,2 @@
-- AddForeignKey
ALTER TABLE `pending_tools` ADD CONSTRAINT `pending_tools_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1 @@
ALTER TABLE `daily_report_items` ADD COLUMN `hot_score` INT NOT NULL DEFAULT 0;
@@ -0,0 +1,44 @@
-- AlterTable
ALTER TABLE `skills` ADD COLUMN `last_reviewed_at` DATETIME(3) NULL,
ADD COLUMN `github_stars_history` JSON NULL;
-- CreateTable
CREATE TABLE `skill_reviews` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`skill_id` INTEGER NOT NULL,
`capability` DOUBLE NOT NULL,
`dev_exp` DOUBLE NOT NULL,
`cost_license` DOUBLE NOT NULL,
`community` DOUBLE NOT NULL,
`performance` DOUBLE NOT NULL,
`overall` DOUBLE NOT NULL,
`reviews` JSON NOT NULL,
`long_article` TEXT NULL,
`video_script` TEXT NULL,
`social_cards` JSON NULL,
`status` ENUM('DRAFT', 'PUBLISHED', 'REJECTED', 'OUTDATED') NOT NULL DEFAULT 'DRAFT',
`reviewed_at` DATETIME(3) NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `skill_reviews_skill_id_key`(`skill_id`),
INDEX `skill_reviews_skill_id_idx`(`skill_id`),
INDEX `skill_reviews_overall_idx`(`overall`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `review_generation_logs` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`skill_id` INTEGER NOT NULL,
`status` VARCHAR(20) NOT NULL,
`prompt` TEXT NOT NULL,
`response` TEXT NULL,
`error` TEXT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
INDEX `review_generation_logs_skill_id_idx`(`skill_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- AddForeignKey
ALTER TABLE `skill_reviews` ADD CONSTRAINT `skill_reviews_skill_id_fkey` FOREIGN KEY (`skill_id`) REFERENCES `skills`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
+3
View File
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "mysql"
+404
View File
@@ -0,0 +1,404 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
}
model Category {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
slug String @unique @db.VarChar(50)
icon String? @db.VarChar(100)
parentId Int? @map("parent_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 Category? @relation("CategoryToCategory", fields: [parentId], references: [id])
children Category[] @relation("CategoryToCategory")
@@map("categories")
}
model SkillCategory {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
slug String @unique @db.VarChar(50)
icon String? @db.VarChar(100)
parentId Int? @map("parent_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 SkillCategory? @relation("SkillCategoryToSkillCategory", fields: [parentId], references: [id])
children SkillCategory[] @relation("SkillCategoryToSkillCategory")
@@map("skill_categories")
}
model Tool {
id Int @id @default(autoincrement())
name String @db.VarChar(100)
slug String @unique @db.VarChar(100)
categoryId Int @map("category_id")
description String @db.Text
logoUrl String? @map("logo_url") @db.VarChar(255)
websiteUrl String @map("website_url") @db.VarChar(255)
pricingModel PricingModel @default(freemium) @map("pricing_model")
pricingDetail String? @map("pricing_detail") @db.VarChar(200)
features Json?
tags Json?
viewCount Int @default(0) @map("view_count")
status Status @default(draft)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
category Category @relation(fields: [categoryId], references: [id])
favorites Favorite[]
browsingHistory BrowsingHistory[]
reviews Review[]
collectionItems CollectionItem[]
@@index([categoryId, status])
@@fulltext([name, description])
@@map("tools")
}
model PendingTool {
id Int @id @default(autoincrement())
name String @db.VarChar(100)
slug String? @db.VarChar(100)
categoryId Int? @map("category_id")
description String? @db.Text
logoUrl String? @map("logo_url") @db.VarChar(255)
websiteUrl String? @map("website_url") @db.VarChar(255)
pricingModel PricingModel? @default(freemium) @map("pricing_model")
pricingDetail String? @map("pricing_detail") @db.VarChar(200)
features Json?
tags Json?
sourceUrl String? @map("source_url") @db.VarChar(255)
status PendingStatus @default(pending)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
category Category? @relation(fields: [categoryId], references: [id])
@@map("pending_tools")
}
model Skill {
id Int @id @default(autoincrement())
name String @db.VarChar(100)
slug String @unique @db.VarChar(100)
categoryId Int @map("category_id")
description String @db.Text
logoUrl String? @map("logo_url") @db.VarChar(255)
sourceUrl String @map("source_url") @db.VarChar(255)
sourceType String @default("gitee") @map("source_type") @db.VarChar(20)
rating Float @default(0) @db.Float
features Json?
tags Json?
viewCount Int @default(0) @map("view_count")
status Status @default(draft)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
category SkillCategory @relation(fields: [categoryId], references: [id])
favorites Favorite[]
browsingHistory BrowsingHistory[]
reviews Review[]
collectionItems CollectionItem[]
skillReview SkillReview?
lastReviewedAt DateTime? @map("last_reviewed_at")
githubStarsHistory Json? @map("github_stars_history")
@@index([categoryId, status])
@@map("skills")
}
model PendingSkill {
id Int @id @default(autoincrement())
name String @db.VarChar(100)
slug String? @db.VarChar(100)
categoryId Int? @map("category_id")
description String? @db.Text
logoUrl String? @map("logo_url") @db.VarChar(255)
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 SkillCategory? @relation(fields: [categoryId], references: [id])
@@map("pending_skills")
}
enum PricingModel {
free
freemium
paid
subscription
}
enum Status {
draft
published
}
enum PendingStatus {
pending
approved
rejected
}
model SystemConfig {
id Int @id @default(autoincrement())
key String @unique @db.VarChar(50)
value Json
@@map("system_configs")
}
model User {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
passwordHash String? @db.VarChar(255)
name String? @db.VarChar(100)
avatarUrl String?
oauthProvider String? @db.VarChar(50)
oauthId String? @unique @db.VarChar(255)
role String @default("user") @db.VarChar(20)
roleId Int? @map("role_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
assignedRole Role? @relation(fields: [roleId], references: [id])
favorites Favorite[]
browsingHistory BrowsingHistory[]
reviews Review[]
collections Collection[]
@@unique([oauthProvider, oauthId])
@@map("users")
}
model 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[]
@@map("roles")
}
model 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[]
@@index([groupName, sortOrder])
@@map("permissions")
}
model RolePermission {
roleId Int @map("role_id")
permissionId Int @map("permission_id")
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
@@id([roleId, permissionId])
@@map("role_permissions")
}
model Favorite {
id Int @id @default(autoincrement())
userId Int @map("user_id")
toolId Int? @map("tool_id")
skillId Int? @map("skill_id")
createdAt DateTime @default(now()) @map("created_at")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade)
skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade)
@@unique([userId, toolId])
@@unique([userId, skillId])
@@index([userId])
@@map("favorites")
}
model BrowsingHistory {
id Int @id @default(autoincrement())
userId Int @map("user_id")
toolId Int? @map("tool_id")
skillId Int? @map("skill_id")
viewedAt DateTime @default(now()) @updatedAt @map("viewed_at")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade)
skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade)
@@unique([userId, toolId])
@@unique([userId, skillId])
@@index([userId, viewedAt])
@@map("browsing_histories")
}
model Review {
id Int @id @default(autoincrement())
userId Int @map("user_id")
toolId Int? @map("tool_id")
skillId Int? @map("skill_id")
rating Int?
comment String @db.Text
createdAt DateTime @default(now()) @map("created_at")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade)
skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade)
@@unique([userId, toolId])
@@unique([userId, skillId])
@@index([toolId, createdAt])
@@index([skillId, createdAt])
@@map("reviews")
}
model Collection {
id Int @id @default(autoincrement())
userId Int @map("user_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 User @relation(fields: [userId], references: [id], onDelete: Cascade)
items CollectionItem[]
@@index([userId])
@@map("collections")
}
model CollectionItem {
id Int @id @default(autoincrement())
collectionId Int @map("collection_id")
toolId Int? @map("tool_id")
skillId Int? @map("skill_id")
addedAt DateTime @default(now()) @map("added_at")
collection Collection @relation(fields: [collectionId], references: [id], onDelete: Cascade)
tool Tool? @relation(fields: [toolId], references: [id], onDelete: Cascade)
skill Skill? @relation(fields: [skillId], references: [id], onDelete: Cascade)
@@unique([collectionId, toolId])
@@unique([collectionId, skillId])
@@index([collectionId])
@@map("collection_items")
}
model DailyReport {
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[]
@@index([date])
@@index([status])
@@map("daily_reports")
}
model DailyReportItem {
id Int @id @default(autoincrement())
reportId Int @map("report_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 DailyReport @relation(fields: [reportId], references: [id], onDelete: Cascade)
@@index([reportId, sortOrder])
@@map("daily_report_items")
}
model SkillReview {
id Int @id @default(autoincrement())
skillId Int @unique @map("skill_id")
skill Skill @relation(fields: [skillId], references: [id])
capability Float
devExp Float @map("dev_exp")
costLicense Float @map("cost_license")
community Float
performance Float
overall Float
reviews Json
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 @map("reviewed_at")
createdAt DateTime @default(now()) @map("created_at")
@@index([skillId])
@@index([overall])
@@map("skill_reviews")
}
model ReviewGenerationLog {
id Int @id @default(autoincrement())
skillId Int @map("skill_id")
status String @db.VarChar(20)
prompt String @db.Text
response String? @db.Text
error String? @db.Text
createdAt DateTime @default(now()) @map("created_at")
@@index([skillId])
@@map("review_generation_logs")
}
enum ReviewStatus {
DRAFT
PUBLISHED
REJECTED
OUTDATED
}
+41
View File
@@ -0,0 +1,41 @@
import { PrismaClient } from "@prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
const adapter = new PrismaMariaDb(process.env.DATABASE_URL!);
const prisma = new PrismaClient({ adapter });
const categories = [
{ name: "文本生成", slug: "text-generation", icon: "", sortOrder: 1 },
{ name: "图像生成", slug: "image-generation", icon: "", sortOrder: 2 },
{ name: "视频生成", slug: "video-generation", icon: "", sortOrder: 3 },
{ name: "音频处理", slug: "audio-processing", icon: "", sortOrder: 4 },
{ name: "代码助手", slug: "code-assistant", icon: "", sortOrder: 5 },
{ name: "办公效率", slug: "office-efficiency", icon: "", sortOrder: 6 },
{ name: "AI 角色", slug: "ai-character", icon: "", sortOrder: 7 },
{ name: "设计工具", slug: "design-tools", icon: "", sortOrder: 8 },
{ name: "数据分析", slug: "data-analysis", icon: "", sortOrder: 9 },
{ name: "内容检测", slug: "content-detection", icon: "", sortOrder: 10 },
];
async function main() {
console.log("Seeding categories...");
for (const category of categories) {
await prisma.category.upsert({
where: { slug: category.slug },
update: { name: category.name, sortOrder: category.sortOrder },
create: category,
});
}
console.log(`Seeded ${categories.length} categories.`);
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+87
View File
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 582.36 178.41" style="enable-background:new 0 0 582.36 178.41;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_1_);}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st2{fill:#002941;}
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#002941;}
.st4{fill:#666666;}
</style>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="14.1598" y1="166.454" x2="165.3124" y2="11.5845">
<stop offset="0.1326" style="stop-color:#E84709"/>
<stop offset="1" style="stop-color:#F19200"/>
</linearGradient>
<path class="st0" d="M0.35,0h178.41v178.41H0.35V0z"/>
<path class="st1" d="M90.15,138.74c15.31-33.86,49.32-57.44,88.86-57.58v5.97c-43.49,0.14-79.89,30.39-89.44,71
c-7.7-33.76-33.92-60.46-67.42-68.84C62.42,79.49,92.34,43.25,92.48,0h6.33c0,39.95-23.94,74.3-58.25,89.51
C62.54,99.25,80.25,116.85,90.15,138.74z M0.35,85.33c-0.12,0-0.24,0-0.35,0v-5.97c0.12,0,0.24,0,0.35,0
c43.83,0,79.36-35.53,79.36-79.36h5.97C85.68,47.13,47.48,85.33,0.35,85.33z M0.65,73.39c-0.22,0-0.43-0.01-0.65-0.01v-4.77
c0.12,0,0.24,0.01,0.35,0.01c37.57,0,68.02-30.46,68.02-68.02c0-0.2-0.01-0.4-0.02-0.6h5.38c0,0.1,0,0.2,0,0.3
C73.75,40.67,41.02,73.39,0.65,73.39z M85.08,178.41h-5.97C78.79,134.94,43.52,99.78,0,99.65v-5.97
C46.81,93.82,84.76,131.64,85.08,178.41z M73.74,178.41h-5.38c-0.32-37.29-30.64-67.43-68.01-67.43c-0.12,0-0.24,0.01-0.35,0.01
v-5.37c0.22,0,0.43-0.01,0.65-0.01C40.92,105.62,73.58,138.18,73.74,178.41z M179.01,93.69v5.97c-43.47,0.19-78.68,35.32-79,78.76
h-5.97C94.36,131.68,132.25,93.88,179.01,93.69z M179.01,105.62v5.39c-36.93,0.51-66.74,30.43-67.06,67.4h-5.38
C106.73,138.4,139.04,105.97,179.01,105.62z"/>
<path class="st2" d="M576.41,98.13V19h5.95v79.13H576.41z M547.12,22.06h5.95V94.2h-5.95V22.06z M505.24,93.94
c10.49-9.26,13.12-17.91,13.12-35.55V31.35h0.01c-0.25-3.95-4.27-4.75-4.97-4.86l-50,0.01l-3.58,12.09h20.9
c6.03,0,11.02,4.98,11.02,11V97.8c0-0.01-4.98,0-11.02,0h-43.19c-6.03,0-11.1-4.98-11.1-11V49.59c0-2.95,0.01-10.03,0.01-11.01
c0-0.02,8.02,0,11.1,0h16.18l3.58-12.09h-36.17v-5.82c0,0,95.72,0.01,92.14,0.01c0.41,0,0.79,0.02,1.15,0.06
c2.78,0.21,4.89,1.23,6.73,3.07c2.84,2.84,3.1,6.39,3.11,7.53h0.04v27.04c0,19.74-2.94,29.35-15.01,40L505.24,93.94z M432.44,86.8
c0,2.8,2.19,5.07,5.07,5.07h43.19c2.8,0,5.07,0.03,5.07,0.01V70.82h-53.34V86.8z M432.48,44.53c-0.02,0-0.03,2.18-0.03,5.07v15.2
h53.34v-15.2c0-2.88-2.27-5.07-5.07-5.07H432.48z"/>
<path class="st2" d="M301.96,30.36h9.5v15.28h-9.5v5.51h9.5V86.9h5.34V68.53h7.85v-5.51h-7.85V51.15h7.85v-5.51h-7.85V30.36h7.85
v-5.51h-7.85V19h-5.34v5.85h-9.5V30.36z"/>
<path class="st2" d="M371.05,64.5c2.35,7.48,3.78,15.44,4.03,22.48h5.38c-0.19-5.86-1.31-17.29-6.46-30.42l-0.06-0.14l0.06-0.14
l6.22-14.23v-7.76c0-5.28-0.09-7.5-2.28-9.28c-2.18-1.77-5.31-1.77-9.64-1.77h-11.57v5.51h11.57c6.45,0,6.7,0.21,6.7,5.54
l-0.03,6.68l-3.92,8.97l-0.31-0.62c-2.04-4.07-4.15-7.57-6.43-10.71h-7.09c4.3,5.06,7.96,11.05,10.87,17.82l0.06,0.14l-0.06,0.14
l-13.2,30.26h5.71l10.18-23.31L371.05,64.5z"/>
<path class="st2" d="M351.02,92.84V19h-25.68v5.51h3.9l0.02,58.86l0,0c0,2.29,0.81,3.14,3.21,2.63l0,0l13.23-2.77v9.62h-28.36
c-8.24,0-9.91-1.11-9.91-6.62v-23.2h-5.33v23.2c0,12.13,9.54,12.13,15.24,12.13h63.16v-5.51H351.02z M345.68,38.61h-8.23v5.51h8.23
v13.41h-8.23V61l0.01-0.1c0,1.15,0.88,2.07,1.99,2.12h6.23V77.6l-10.26,2.15c-0.59,0.06-0.83-0.19-0.85-0.8V24.51h11.11V38.61z"/>
<path class="st3" d="M400.97,54.1c2.48,0,4.48,2.01,4.48,4.48c0,2.48-2.01,4.48-4.48,4.48c-2.48,0-4.48-2.01-4.48-4.48
C396.49,56.11,398.5,54.1,400.97,54.1z"/>
<path class="st2" d="M211.45,27.43h2.6c0,0-0.05,9.26-0.05,17.13c0,9.91,10.3,10.88,10.3,10.88h2.65v12.87h-14.89v5.95h14.89
c0,0,0,17.35,0,13.54c0,7.14,7.12,7.48,7.12,7.48l15.82-1.14l-0.79-5.95l-11.48,1.13c0,0-4.72,0.52-4.72-4.95
c0-4.72,0-10.11,0-10.11h15.32v-5.95h-15.32V55.45h2.45c6.04,0,11.03-4.99,11.03-11.03V34.34h-5.95v10.07
c0,2.8-2.28,5.04-5.08,5.04h-8.15c0,0-6.73,0.49-6.73-5.07c0-6.43,0-16.96,0-16.96h28.46v-5.95h-37.48V27.43z M253.31,44.59
l14.97,24.95c-5.25,10.51-11.38,18.48-18.04,25.04l4.2,4.2c6.39-6.3,12.26-13.66,17.51-23.29l13.92,23.12l5.17-3.06l-15.94-26.36
c4.38-9.63,7.6-17.92,10.49-32.28c0,0,0.43-1.17,0.05-3.4c-0.44-2.59-2.55-5.86-7.86-5.83c-8.81,0.06-17.64,0-17.64,0l1.23-7.71
l-6.04-0.96l-2.28,14.62h20.17c4.33,0,6.38,2.11,5.41,5.94c-2.44,9.65-4.29,16.18-7.28,23.39l-12.96-21.45L253.31,44.59z"/>
<g>
<g>
<path class="st4" d="M231.11,141.72v-0.15c1.97-0.66,3.13-2.66,3.13-4.74c0-3.97-3.25-5.4-7.76-5.4h-6.8v21.96h7.34
c4.86,0,8.41-2.09,8.41-6.44C235.43,143.95,233.61,142.25,231.11,141.72z M223.14,134.11h3.04c3.1,0,4.65,0.87,4.65,3.16
c0,2.06-1.4,3.31-4.74,3.31h-2.95V134.11z M226.63,150.67h-3.49v-7.46h3.49c3.49,0,5.4,1.07,5.4,3.55
C232.03,149.44,230.06,150.67,226.63,150.67z M263.93,136.55c-3.85,0-7.49,3.31-7.49,8.65c0,5.4,3.55,8.56,8,8.56
c2.15,0,4.03-0.72,5.55-1.73l-1.19-2.18c-1.19,0.78-2.45,1.22-3.91,1.22c-2.83,0-4.8-1.88-5.07-5.01h10.65
c0.09-0.39,0.15-1.07,0.15-1.73C270.61,139.69,268.28,136.55,263.93,136.55z M259.78,143.72c0.33-2.89,2.15-4.48,4.21-4.48
c2.39,0,3.67,1.64,3.67,4.48H259.78z M298.62,143.8c-1.79-0.66-3.49-1.19-3.49-2.6c0-1.13,0.84-2.03,2.63-2.03
c1.37,0,2.54,0.6,3.67,1.43l1.61-2.12c-1.34-1.04-3.13-1.94-5.34-1.94c-3.61,0-5.82,2.06-5.82,4.8c0,2.77,2.51,3.94,4.68,4.77
c1.79,0.69,3.64,1.34,3.64,2.83c0,1.25-0.92,2.21-2.89,2.21c-1.76,0-3.19-0.72-4.65-1.88l-1.61,2.21
c1.58,1.31,3.91,2.27,6.18,2.27c4.06,0,6.24-2.24,6.24-4.98C303.46,145.68,300.92,144.67,298.62,143.8z M334.4,150.76
c-3.88,0-6.33-3.19-6.33-8.41c0-5.16,2.63-8.32,6.42-8.32c1.79,0,3.16,0.81,4.3,1.97l1.88-2.21c-1.34-1.46-3.49-2.77-6.24-2.77
c-5.55,0-9.91,4.3-9.91,11.46c0,7.19,4.24,11.31,9.76,11.31c2.83,0,5.07-1.13,6.83-3.16l-1.85-2.18
C337.95,149.86,336.39,150.76,334.4,150.76z M371.6,136.55c-2.24,0-3.88,1.22-5.31,2.6l0.12-3.25v-6.3h-3.4v23.78h3.4v-11.64
c1.46-1.46,2.51-2.24,4.03-2.24c1.94,0,2.77,1.13,2.77,3.97v9.91h3.43v-10.32C376.64,138.88,375.09,136.55,371.6,136.55z
M406.18,136.55c-2.63,0-4.92,1.07-6.62,2.15l1.28,2.33c1.4-0.9,3.01-1.67,4.74-1.67c2.42,0,3.1,1.67,3.13,3.58
c-6.83,0.75-9.82,2.57-9.82,6.09c0,2.89,2,4.74,4.83,4.74c1.97,0,3.73-0.98,5.22-2.27h0.09l0.3,1.88h2.8v-9.88
C412.15,139.15,410.27,136.55,406.18,136.55z M408.71,149.15c-1.34,1.22-2.51,1.91-3.94,1.91c-1.46,0-2.57-0.66-2.57-2.27
c0-1.85,1.64-3.07,6.5-3.67V149.15z M443.92,136.55c-2.24,0-3.91,1.22-5.43,2.69h-0.09l-0.27-2.27h-2.8v16.41h3.4v-11.64
c1.46-1.46,2.51-2.24,4.03-2.24c1.94,0,2.77,1.13,2.77,3.97v9.91h3.43v-10.32C448.96,138.88,447.41,136.55,443.92,136.55z
M480.86,136.55c-2.24,0-3.91,1.22-5.43,2.69h-0.09l-0.27-2.27h-2.8v16.41h3.4v-11.64c1.46-1.46,2.51-2.24,4.03-2.24
c1.94,0,2.77,1.13,2.77,3.97v9.91h3.43v-10.32C485.9,138.88,484.35,136.55,480.86,136.55z M515.52,136.55
c-3.85,0-7.49,3.31-7.49,8.65c0,5.4,3.55,8.56,8,8.56c2.15,0,4.03-0.72,5.55-1.73l-1.19-2.18c-1.19,0.78-2.45,1.22-3.91,1.22
c-2.83,0-4.8-1.88-5.07-5.01h10.65c0.09-0.39,0.15-1.07,0.15-1.73C522.21,139.69,519.88,136.55,515.52,136.55z M511.38,143.72
c0.33-2.89,2.15-4.48,4.21-4.48c2.39,0,3.67,1.64,3.67,4.48H511.38z M548.61,150.97c-0.42,0-0.84-0.33-0.84-1.25V129.6h-3.4
v19.93c0,2.66,0.92,4.24,3.4,4.24c0.84,0,1.43-0.12,1.85-0.27l-0.45-2.6C548.88,150.97,548.76,150.97,548.61,150.97z
M577.43,143.8c-1.79-0.66-3.49-1.19-3.49-2.6c0-1.13,0.84-2.03,2.63-2.03c1.37,0,2.54,0.6,3.67,1.43l1.61-2.12
c-1.34-1.04-3.13-1.94-5.34-1.94c-3.61,0-5.82,2.06-5.82,4.8c0,2.77,2.51,3.94,4.68,4.77c1.79,0.69,3.64,1.34,3.64,2.83
c0,1.25-0.92,2.21-2.89,2.21c-1.76,0-3.19-0.72-4.65-1.88l-1.61,2.21c1.58,1.31,3.91,2.27,6.18,2.27c4.06,0,6.24-2.24,6.24-4.98
C582.26,145.68,579.73,144.67,577.43,143.8z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,4 @@
<svg width="46" height="40" viewBox="0 0 46 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.491 0.691513H15.2473L10.505 10.7684H29.491V0.691513ZM38.9579 17.8406L36.5917 11.4927L34.2255 17.8406L27.8309 20.1895L34.2255 22.5385L36.5917 28.8864L38.9579 22.5385L45.3524 20.1895L38.9579 17.8406ZM10.505 29.6145H29.491V39.6913H14.1613L10.505 29.6145ZM0.352827 10.767L0.3526 29.6145H10.5037L10.5037 10.767H0.352827Z" fill="#683BFF"/>
<path d="M36.6385 11.4754L36.5917 11.3497L36.5448 11.4754L34.1867 17.8018L27.8137 20.1428L27.6859 20.1897L27.8137 20.2366L34.1867 22.5777L36.5448 28.904L36.5917 29.0297L36.6385 28.904L38.9967 22.5777L45.3697 20.2366L45.4975 20.1897L45.3697 20.1428L38.9967 17.8018L36.6385 11.4754Z" fill="#6FEA2A" stroke="black" stroke-width="0.1"/>
</svg>

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Some files were not shown because too many files have changed in this diff Show More