docs(stage-2): standardize project guides and PRDs
This commit is contained in:
@@ -1528,35 +1528,35 @@ Sitemap: ${siteUrl}/sitemap.xml
|
|||||||
link: '/zh-cn/stage-2/frontend/2.5-hogwarts-portraits/'
|
link: '/zh-cn/stage-2/frontend/2.5-hogwarts-portraits/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '大作业 1:第一个 SaaS 全栈应用——文案生成网站',
|
text: '大作业 1:AI 营销文案 SaaS 开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/copywriting-platform-supabase/'
|
link: '/zh-cn/stage-2/assignments/copywriting-platform-supabase/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '大作业 2:在线考试与管理系统',
|
text: '大作业 2:在线考试与管理系统开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/exam-management-express/'
|
link: '/zh-cn/stage-2/assignments/exam-management-express/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '扩展作业:现代网页落地页',
|
text: '扩展作业:现代 AI 生图 SaaS 开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/modern-landing-page/'
|
link: '/zh-cn/stage-2/assignments/modern-landing-page/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '扩展作业:自制 Dify 智能体平台',
|
text: '扩展作业:类 Dify 智能体平台开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/custom-dify-agent-platform/'
|
link: '/zh-cn/stage-2/assignments/custom-dify-agent-platform/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '扩展作业:智能旅游规划 Agent 平台',
|
text: '扩展作业:智能旅游规划 Agent 平台开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/travel-planning-agent-platform/'
|
link: '/zh-cn/stage-2/assignments/travel-planning-agent-platform/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '扩展作业:电影推荐网(Spring Boot)',
|
text: '扩展作业:Spring Boot 电影推荐系统开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/movie-recommendation-springboot/'
|
link: '/zh-cn/stage-2/assignments/movie-recommendation-springboot/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '扩展作业:简单买菜微服务网站',
|
text: '扩展作业:生鲜电商微服务系统开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/simple-grocery-microservices/'
|
link: '/zh-cn/stage-2/assignments/simple-grocery-microservices/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '扩展作业:交通大数据可视化分析(Go)',
|
text: '扩展作业:Go 交通数据分析平台开发实战',
|
||||||
link: '/zh-cn/stage-2/assignments/traffic-data-visualization-go/'
|
link: '/zh-cn/stage-2/assignments/traffic-data-visualization-go/'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
+65
-9
@@ -938,58 +938,114 @@
|
|||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/ai-capabilities/2.1-dify-knowledge-base/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/ai-capabilities/2.1-dify-knowledge-base/"/>
|
||||||
<xhtml:link rel="alternate" hreflang="en" href="https://datawhalechina.github.io/easy-vibe/en/stage-2/ai-capabilities/2.1-dify-knowledge-base/"/>
|
<xhtml:link rel="alternate" hreflang="en" href="https://datawhalechina.github.io/easy-vibe/en/stage-2/ai-capabilities/2.1-dify-knowledge-base/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/copywriting-platform-supabase/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:14:27.746Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/copywriting-platform-supabase/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/copywriting-platform-supabase/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/copywriting-platform-supabase/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/copywriting-platform-supabase/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/copywriting-platform-supabase/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/custom-dify-agent-platform/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:14:27.747Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/custom-dify-agent-platform/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/custom-dify-agent-platform/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/custom-dify-agent-platform/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/custom-dify-agent-platform/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/custom-dify-agent-platform/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/exam-management-express/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:14:27.748Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/exam-management-express/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/exam-management-express/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/exam-management-express/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/exam-management-express/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/exam-management-express/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/modern-landing-page/PRD/</loc>
|
||||||
|
<lastmod>2026-03-30T09:59:56.848Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/modern-landing-page/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/modern-landing-page/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/modern-landing-page/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/modern-landing-page/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/modern-landing-page/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/movie-recommendation-springboot/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:15:20.951Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/movie-recommendation-springboot/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/movie-recommendation-springboot/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/movie-recommendation-springboot/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/movie-recommendation-springboot/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/movie-recommendation-springboot/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/simple-grocery-microservices/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:15:20.951Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/simple-grocery-microservices/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/simple-grocery-microservices/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/simple-grocery-microservices/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/simple-grocery-microservices/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/simple-grocery-microservices/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/traffic-data-visualization-go/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:15:20.951Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/traffic-data-visualization-go/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/traffic-data-visualization-go/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/traffic-data-visualization-go/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/traffic-data-visualization-go/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/traffic-data-visualization-go/"/>
|
||||||
</url>
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/travel-planning-agent-platform/PRD/</loc>
|
||||||
|
<lastmod>2026-03-31T04:15:20.950Z</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>0.8</priority>
|
||||||
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/travel-planning-agent-platform/PRD/"/>
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/travel-planning-agent-platform/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/travel-planning-agent-platform/</loc>
|
||||||
<lastmod>2026-03-26T11:20:31+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/travel-planning-agent-platform/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/assignments/travel-planning-agent-platform/"/>
|
||||||
@@ -1108,7 +1164,7 @@
|
|||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/</loc>
|
<loc>https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/</loc>
|
||||||
<lastmod>2026-03-29T15:16:07+08:00</lastmod>
|
<lastmod>2026-03-29T19:37:03+08:00</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/"/>
|
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://datawhalechina.github.io/easy-vibe/zh-cn/stage-2/"/>
|
||||||
|
|||||||
@@ -0,0 +1,361 @@
|
|||||||
|
# PRD:AI 营销文案 SaaS 平台
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:先明确产品边界、页面结构、数据模型与支付闭环,再进入开发。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个面向独立开发者、小团队和内容运营者的 AI 营销文案 SaaS。它不是单次调用模型的 Demo,而是一套带登录、生成、历史、套餐、后台管理的完整产品。
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个支持注册登录、文案生成、历史管理、套餐付费和后台运营的 AI 营销文案工作台。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
WWW["www.xxx.com<br/>官网前台"] --> API["应用 API / 管理 API"]
|
||||||
|
APP["app.xxx.com<br/>用户工作台"] --> API
|
||||||
|
ADMIN["admin.xxx.com<br/>后台管理台"] --> API
|
||||||
|
API --> AUTH["Supabase Auth"]
|
||||||
|
API --> DB["Supabase Postgres"]
|
||||||
|
API --> PAY["Stripe"]
|
||||||
|
API --> LLM["第三方大模型 API"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.1 技术选型建议
|
||||||
|
|
||||||
|
- 前端框架:`Next.js App Router`
|
||||||
|
- 用户鉴权:`Supabase Auth`
|
||||||
|
- 数据库:`Supabase Postgres`
|
||||||
|
- 支付:`Stripe`
|
||||||
|
- AI 能力:统一后端适配层对接第三方大模型 API
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 用户工作台:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.2 竞品参考(官方)
|
||||||
|
|
||||||
|
- [Jasper](https://www.jasper.ai/)
|
||||||
|
- [Copy.ai](https://www.copy.ai/)
|
||||||
|
|
||||||
|
## 1.3 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考这些真实产品的做法:
|
||||||
|
|
||||||
|
- 借鉴 `Jasper` 的官网表达方式:强调营销团队场景、价值主张、平台能力和 CTA 转化
|
||||||
|
- 借鉴 `Jasper` 的工作台思路:让“生成”不是一个孤立按钮,而是一个带上下文和多种产出类型的工作空间
|
||||||
|
- 借鉴 `Copy.ai` 的产品形态:把不同输出场景拆成清晰工作流,而不是把所有功能堆在一个输入框里
|
||||||
|
- 因此本项目的首页、工作台、套餐页和后台运营页,都应该更像一个真实营销 SaaS,而不是单页工具
|
||||||
|
|
||||||
|
## 1.4 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `Jasper` 官网首页
|
||||||
|
- 重点看:Hero、品牌价值表达、工作流/Agent 介绍、演示 CTA、企业化信任背书
|
||||||
|
- `Jasper` 的 Agent / Workflow 类页面
|
||||||
|
- 重点看:不是单纯展示一个文本框,而是强调“场景 -> 输入上下文 -> 输出结果”的完整工作流
|
||||||
|
- `Copy.ai` 的 Workflow / GTM 类页面
|
||||||
|
- 重点看:不同营销任务如何拆成不同工作区和模板入口
|
||||||
|
|
||||||
|
因此本项目建议页面设计不是“一个输入框 + 一个结果框”,而是:
|
||||||
|
|
||||||
|
- 首页负责转化
|
||||||
|
- 工作台负责结构化输入与输出管理
|
||||||
|
- 历史页负责内容复用
|
||||||
|
- 套餐页负责商业化
|
||||||
|
- 后台负责运营视角
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 想快速生成营销文案的独立开发者
|
||||||
|
- 需要批量产出广告、落地页、社媒文案的小团队
|
||||||
|
- 管理套餐、用户和生成记录的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 用户能在 5 分钟内注册并完成第一次文案生成
|
||||||
|
- 用户能查看历史生成结果并二次编辑
|
||||||
|
- 产品能完成从生成到支付升级的基本闭环
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 官网首页
|
||||||
|
- 注册/登录
|
||||||
|
- 文案生成工作台
|
||||||
|
- 历史记录页
|
||||||
|
- 套餐页
|
||||||
|
- 支付/订阅能力
|
||||||
|
- 后台查看用户、生成记录和支付数据
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 团队协作
|
||||||
|
- 多语言翻译链路
|
||||||
|
- 复杂工作流编排
|
||||||
|
- 模板市场
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 游客 | 浏览官网、注册登录 |
|
||||||
|
| 注册用户 | 生成文案、查看历史、管理套餐 |
|
||||||
|
| 管理员 | 查看用户、生成数据、支付和运营数据 |
|
||||||
|
|
||||||
|
## 5. 页面架构
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,10 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 用户工作台 `5` 个大页面
|
||||||
|
- 后台管理台 `4` 个大页面
|
||||||
|
|
||||||
|
### 官网前台
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- Hero 与 CTA
|
||||||
|
- 场景介绍
|
||||||
|
- 输出示例
|
||||||
|
- 套餐预览
|
||||||
|
- FAQ
|
||||||
|
|
||||||
|
### 用户工作台
|
||||||
|
|
||||||
|
#### 2. 登录页 `app:/login`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 邮箱密码登录
|
||||||
|
- 第三方登录
|
||||||
|
- 跳转注册
|
||||||
|
|
||||||
|
#### 3. 注册页 `app:/register`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 新用户注册
|
||||||
|
- 同意条款
|
||||||
|
- 注册完成跳转工作台
|
||||||
|
|
||||||
|
#### 4. 生成工作台 `app:/generate`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 输入产品信息、受众、渠道、卖点
|
||||||
|
- 选择输出类型和语气
|
||||||
|
- 发起生成
|
||||||
|
- 查看生成结果
|
||||||
|
- 保存和再次编辑
|
||||||
|
|
||||||
|
#### 5. 历史记录页 `app:/history`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看历史文案
|
||||||
|
- 按时间/类型筛选
|
||||||
|
- 再次打开、复制、删除
|
||||||
|
|
||||||
|
#### 6. 套餐页 `app:/billing`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看 Free / Pro / Team 套餐
|
||||||
|
- 月付/年付切换
|
||||||
|
- 发起支付
|
||||||
|
- 查看当前套餐权益
|
||||||
|
|
||||||
|
### 后台管理台
|
||||||
|
|
||||||
|
#### 7. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 用户总数
|
||||||
|
- 生成次数
|
||||||
|
- 付费收入
|
||||||
|
- 转化概览
|
||||||
|
|
||||||
|
#### 8. 用户管理 `admin:/users`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看用户列表
|
||||||
|
- 查看套餐状态
|
||||||
|
- 查看最近活跃
|
||||||
|
- 封禁/恢复
|
||||||
|
|
||||||
|
#### 9. 生成记录 `admin:/generations`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看生成内容与次数
|
||||||
|
- 查看失败记录
|
||||||
|
- 查看高频模板和渠道分布
|
||||||
|
|
||||||
|
#### 10. 支付与订阅 `admin:/billing`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看支付订单
|
||||||
|
- 查看订阅状态
|
||||||
|
- 查看退款与失败订单
|
||||||
|
|
||||||
|
## 5.1 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
visitor["访客"] --> home["官网首页"]
|
||||||
|
home --> register["注册 / 登录"]
|
||||||
|
register --> workspace["文案工作台"]
|
||||||
|
workspace --> generate["提交生成任务"]
|
||||||
|
generate --> result["查看生成结果"]
|
||||||
|
result --> history["保存到历史记录"]
|
||||||
|
workspace --> billing["升级套餐"]
|
||||||
|
billing --> pay["Stripe 支付"]
|
||||||
|
pay --> plan["套餐状态更新"]
|
||||||
|
plan --> workspace
|
||||||
|
plan --> admin["后台查看用户/生成/支付数据"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 游客 -> 注册用户
|
||||||
|
- 免费用户 -> 付费用户
|
||||||
|
- 生成中 -> 生成成功 / 生成失败
|
||||||
|
- 订单处理中 -> 支付成功 / 支付失败
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `auth`
|
||||||
|
- `generation`
|
||||||
|
- `history`
|
||||||
|
- `billing`
|
||||||
|
- `analytics`
|
||||||
|
- `admin`
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
profiles (
|
||||||
|
id uuid primary key,
|
||||||
|
email text,
|
||||||
|
role text,
|
||||||
|
plan text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
generation_records (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
input_payload jsonb,
|
||||||
|
output_payload jsonb,
|
||||||
|
channel text,
|
||||||
|
tone text,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
billing_records (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
plan_code text,
|
||||||
|
billing_cycle text,
|
||||||
|
amount_cents int,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 新增注册用户数
|
||||||
|
- 日活跃生成用户数
|
||||||
|
- 文案生成总次数
|
||||||
|
- 生成成功率 / 失败率
|
||||||
|
- 套餐转化率
|
||||||
|
- 付费收入与退款率
|
||||||
|
- 高峰时段生成请求量
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- 模型调用成功率
|
||||||
|
- 接口平均耗时
|
||||||
|
- 支付回调成功率
|
||||||
|
- 数据库连接与慢查询
|
||||||
|
- 关键任务错误日志
|
||||||
|
|
||||||
|
## 7. 功能清单
|
||||||
|
|
||||||
|
必须完成:
|
||||||
|
|
||||||
|
- 官网价值展示
|
||||||
|
- 注册/登录
|
||||||
|
- 结构化文案输入
|
||||||
|
- 文案生成结果展示
|
||||||
|
- 历史记录管理
|
||||||
|
- 套餐与支付
|
||||||
|
- 后台用户与生成数据查看
|
||||||
|
|
||||||
|
可选增强:
|
||||||
|
|
||||||
|
- 文案模板库
|
||||||
|
- 不同语气/渠道预设
|
||||||
|
- 结果二次编辑
|
||||||
|
- 复制和导出
|
||||||
|
- 团队共享工作区
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/auth/register` | 注册 |
|
||||||
|
| `POST` | `/api/auth/login` | 登录 |
|
||||||
|
| `POST` | `/api/generations` | 创建文案生成任务 |
|
||||||
|
| `GET` | `/api/generations/:id` | 获取生成结果 |
|
||||||
|
| `GET` | `/api/history` | 获取历史记录 |
|
||||||
|
| `DELETE` | `/api/history/:id` | 删除历史记录 |
|
||||||
|
| `GET` | `/api/billing/plans` | 获取套餐 |
|
||||||
|
| `POST` | `/api/billing/checkout` | 创建支付会话 |
|
||||||
|
| `GET` | `/api/admin/overview` | 获取后台总览 |
|
||||||
|
| `GET` | `/api/admin/users` | 获取用户列表 |
|
||||||
|
| `GET` | `/api/admin/generations` | 获取生成记录列表 |
|
||||||
|
|
||||||
|
## 9. 非功能要求
|
||||||
|
|
||||||
|
- 生成过程要有清晰加载和失败反馈
|
||||||
|
- 用户历史记录只能自己可见
|
||||||
|
- 支付状态和套餐状态要一致
|
||||||
|
- 后台能按日查看生成量和付费数据
|
||||||
|
- 首页和工作台都需要移动端可用
|
||||||
|
|
||||||
|
## 10. 开发顺序建议
|
||||||
|
|
||||||
|
1. 搭官网和登录注册页
|
||||||
|
2. 实现生成工作台
|
||||||
|
3. 接入鉴权和数据库
|
||||||
|
4. 接入模型生成接口
|
||||||
|
5. 实现历史记录
|
||||||
|
6. 接入支付与套餐
|
||||||
|
7. 实现后台运营页
|
||||||
|
|
||||||
|
## 11. 待确认项
|
||||||
|
|
||||||
|
- 是否默认只做单次生成,不做批量生成
|
||||||
|
- 支付是先做月付,还是月付和年付都做
|
||||||
|
- 是否需要在第一版加入模板库
|
||||||
@@ -1,222 +1,158 @@
|
|||||||
# 大作业 1:第一个 SaaS 全栈应用——文案生成网站
|
# AI 营销文案 SaaS 开发实战
|
||||||
|
|
||||||
第一次做全栈网站,最容易卡住的地方往往不是代码,而是**不知道该做什么**。
|
这个项目不再只是“写一个生成按钮”,而是围绕一份真实 PRD,把一个 AI 营销文案 SaaS 从想法推进到可上线产品。
|
||||||
|
|
||||||
题目太大,功能太散,做到一半发现根本收不住。
|
你会同时看到三件事:
|
||||||
|
|
||||||
所以这次换个思路:不给开放题,直接给你一个明确的方向——做一件完整但不复杂的事。
|
- 项目要做成什么
|
||||||
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
::: tip PRD 入口
|
||||||
打造一个 **AI 营销文案工作台**。用户登录后填写产品信息,一键生成营销文案,自动保存历史记录。需要更多生成次数?升级套餐即可。管理员可在后台查看所有用户、生成记录和支付情况。
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定主题', description: '先把网站的页面和功能定下来' },
|
{ title: '看 PRD', description: '先明确页面、功能、鉴权、数据库、支付与后台范围' },
|
||||||
{ title: '搭前台', description: '首页、登录、工作台先做出来' },
|
{ title: '生成骨架', description: '让 AI 先产出官网、工作台、后台三套界面骨架' },
|
||||||
{ title: '接后端', description: '数据库、生成、支付接起来' },
|
{ title: '监工迭代', description: '逐页验收、补接口、修权限、补支付与数据链路' },
|
||||||
{ title: '做后台与交付', description: '管理台、部署、演示材料补齐' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的 SaaS 原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 先看全景:你最终要做出来的不是“一个页面”,而是一条完整业务链路
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
很多人第一次做全栈项目,最容易犯的错不是不会写代码,而是只盯着某一个页面,结果首页挺好看,后端没接上;生成按钮能点,历史记录没保存;支付能跳转,但数据库根本没更新。
|
这是一个面向独立开发者和内容团队的 AI 营销文案 SaaS:
|
||||||
|
|
||||||
这个项目真正要交付的,是下面这条完整链路:
|
- 官网前台:负责产品介绍、定价、FAQ、注册转化
|
||||||
|
- 用户工作台:负责输入产品信息、生成文案、查看历史、升级套餐
|
||||||
|
- 后台管理台:负责用户、生成记录、支付数据和运营概览
|
||||||
|
|
||||||
|
后端需要接住这些关键能力:
|
||||||
|
|
||||||
|
- 用户鉴权
|
||||||
|
- 文案生成任务
|
||||||
|
- 历史记录持久化
|
||||||
|
- Stripe 支付
|
||||||
|
- 后台用户和生成数据管理
|
||||||
|
|
||||||
|
## 开发过程怎么走?
|
||||||
|
|
||||||
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
|
先确认:
|
||||||
|
|
||||||
|
- 有几个入口:`www / app / admin`
|
||||||
|
- 页面清单是否完整
|
||||||
|
- 后端模块和数据表是否合理
|
||||||
|
- 套餐、支付和后台范围是否收住
|
||||||
|
|
||||||
|
如果 PRD 没拍板,就先不要写代码。
|
||||||
|
|
||||||
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
|
第一轮目标不是做完整闭环,而是先生成:
|
||||||
|
|
||||||
|
- 官网首页
|
||||||
|
- 登录注册
|
||||||
|
- 文案生成工作台
|
||||||
|
- 历史记录页
|
||||||
|
- 套餐页
|
||||||
|
- 后台首页与管理页骨架
|
||||||
|
|
||||||
|
这一步要先把页面结构、路由和信息架构搭出来。
|
||||||
|
|
||||||
|
### 3. 再进入“监工模式”
|
||||||
|
|
||||||
|
你需要重点盯这几件事:
|
||||||
|
|
||||||
|
- 页面结构是不是和 PRD 一致
|
||||||
|
- 登录态和匿名态有没有分清
|
||||||
|
- 生成结果有没有稳定落库
|
||||||
|
- 支付之后套餐状态有没有更新
|
||||||
|
- 后台是不是能看到真实用户、生成和支付数据
|
||||||
|
|
||||||
|
可以把 AI 当执行者,但你自己要做项目经理和验收人。
|
||||||
|
|
||||||
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
visitor["访客"] --> home["首页 / 落地页"]
|
prd["PRD"] --> web["官网前台"]
|
||||||
home --> auth["注册 / 登录"]
|
prd --> app["用户工作台"]
|
||||||
auth --> dashboard["用户工作台"]
|
prd --> admin["后台管理台"]
|
||||||
dashboard --> generate["生成接口 /api/generate"]
|
app --> auth["鉴权"]
|
||||||
generate --> llm["LLM 文案生成"]
|
app --> gen["文案生成任务"]
|
||||||
generate --> generations["generations 表"]
|
gen --> db["数据库"]
|
||||||
dashboard --> history["历史记录读取"]
|
billing["支付与套餐"] --> db
|
||||||
dashboard --> billing["套餐页 /billing"]
|
admin --> analytics["用户 / 生成 / 支付看板"]
|
||||||
billing --> stripe["Stripe Checkout"]
|
|
||||||
stripe --> webhook["支付回调 Webhook"]
|
|
||||||
webhook --> subscriptions["subscriptions 表"]
|
|
||||||
subscriptions --> profile["profiles.plan 更新"]
|
|
||||||
profile --> admin["管理后台 /admin"]
|
|
||||||
admin --> report["查看用户 / 生成记录 / 支付状态"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
只要上面这张图能跑通,你做的就不是课堂 Demo,而是一个真正像产品的最小 SaaS。
|
只要这条链路能跑通,这个项目就不是单点 Demo,而是一个完整 SaaS 原型。
|
||||||
|
|
||||||
## 为什么选这个题目?
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
因为它恰到好处——**涵盖了现代网站该有的所有要素,又不会复杂到失控**。
|
推荐按模块逐步下指令,而不是一句“帮我做完”。
|
||||||
|
|
||||||
- **前台有实际用途**:不是摆设,用户真的来解决问题
|
|
||||||
- **用户系统有登录权限**:区分访客与注册用户
|
|
||||||
- **核心功能是"生成"**:调用 AI 动态产出内容,而非展示静态页面
|
|
||||||
- **数据持久化**:生成结果存入数据库,随时可查
|
|
||||||
- **付费机制**:看起来像正经 SaaS,而非玩具项目
|
|
||||||
- **管理后台**:体验管理员视角,掌控全局
|
|
||||||
|
|
||||||
难度适中:不会简单到只有一个表单,也不会复杂到做一周还找不着北。
|
|
||||||
|
|
||||||
### 先锁定项目边界,别一上来就做“大而全”
|
|
||||||
|
|
||||||
为了让你真的能按时做完,这个项目建议你先只做 **最小可用版本**:
|
|
||||||
|
|
||||||
- 只做 **邮箱注册 / 登录**,先不要接第三方 OAuth
|
|
||||||
- 支付只做 **免费版 + Pro 版** 两档,先不要做优惠券、年付月付切换
|
|
||||||
- AI 生成功能只做 **单次文案生成**,先不要做批量任务队列
|
|
||||||
- 管理后台先做 **查看**,暂时不要求复杂运营操作
|
|
||||||
- 权限只区分 **user / admin** 两种角色
|
|
||||||
|
|
||||||
你会发现,真正难的不是“还能不能继续加功能”,而是“能不能先把主流程稳定交付”。
|
|
||||||
|
|
||||||
## 1. 定主题:先搞清楚要做什么
|
|
||||||
|
|
||||||
网站名称:**LaunchKit**
|
|
||||||
|
|
||||||
定位:AI 营销文案工作台
|
|
||||||
|
|
||||||
目标用户:独立开发者、小商家、内容运营者,以及想快速搞定 Landing Page 的人。
|
|
||||||
|
|
||||||
他们来这里不是为了闲聊——就是想**快速拿到能用的营销文案**。
|
|
||||||
|
|
||||||
### 核心功能
|
|
||||||
|
|
||||||
别想太复杂,核心就一件事:
|
|
||||||
|
|
||||||
**用户输入**:产品名、一句话介绍、目标用户、3 个卖点、投放渠道
|
|
||||||
|
|
||||||
**系统输出**:主标题、副标题、CTA 按钮文案、3 版短文案、1 版长文案
|
|
||||||
|
|
||||||
生成结果自动存入账户,下次登录随时查看。
|
|
||||||
|
|
||||||
### 页面规划
|
|
||||||
|
|
||||||
按这 6 个页面来做:
|
|
||||||
|
|
||||||
| 页面 | 路径 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| 首页 | `/` | 清晰传达产品价值,放置注册/登录入口 |
|
|
||||||
| 登录页 | `/login` | 简洁的登录表单 |
|
|
||||||
| 注册页 | `/register` | 简洁的注册表单 |
|
|
||||||
| 工作台 | `/dashboard` | 填写信息、生成文案、查看结果 |
|
|
||||||
| 套餐页 | `/billing` | 展示免费版与 Pro 版,跳转 Stripe 付款 |
|
|
||||||
| 管理后台 | `/admin` | 管理员查看用户、生成记录、支付状态 |
|
|
||||||
|
|
||||||
### 数据模型
|
|
||||||
|
|
||||||
三张核心表足够:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
profiles (
|
|
||||||
id uuid primary key,
|
|
||||||
email text,
|
|
||||||
role text, -- user / admin
|
|
||||||
plan text, -- free / pro
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
generations (
|
|
||||||
id uuid primary key,
|
|
||||||
user_id uuid,
|
|
||||||
product_name text,
|
|
||||||
target_channel text,
|
|
||||||
input_payload jsonb,
|
|
||||||
result_payload jsonb,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
subscriptions (
|
|
||||||
id uuid primary key,
|
|
||||||
user_id uuid,
|
|
||||||
stripe_customer_id text,
|
|
||||||
stripe_subscription_id text,
|
|
||||||
plan text,
|
|
||||||
status text,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
到这一步,整个网站的骨架已经清晰。
|
|
||||||
|
|
||||||
### 推荐开发顺序
|
|
||||||
|
|
||||||
不要按“想到什么做什么”,而要按依赖关系推进:
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
A["首页 / 登录 / Dashboard 骨架"] --> B["Supabase Auth"]
|
|
||||||
B --> C["profiles / generations / subscriptions"]
|
|
||||||
C --> D["生成接口 + 历史记录"]
|
|
||||||
D --> E["Stripe 支付 + 套餐限制"]
|
|
||||||
E --> F["Admin 后台"]
|
|
||||||
F --> G["部署 / README / 演示视频"]
|
|
||||||
```
|
|
||||||
|
|
||||||
这个顺序的好处是:每一步都能看到阶段性成果,也更容易排查问题。
|
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
|
||||||
<ClientOnly>
|
|
||||||
<StepBar :active="1" :items="[
|
|
||||||
{ title: '定主题', description: '先把网站的页面和功能定下来' },
|
|
||||||
{ title: '搭前台', description: '首页、登录、工作台先做出来' },
|
|
||||||
{ title: '接后端', description: '数据库、生成、支付接起来' },
|
|
||||||
{ title: '做后台与交付', description: '管理台、部署、演示材料补齐' }
|
|
||||||
]" />
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 2. 搭前台:先把页面做出来
|
|
||||||
|
|
||||||
这一步先别碰数据库,也别急着接支付——**先把前台骨架搭起来**。
|
|
||||||
|
|
||||||
### 技术栈
|
|
||||||
|
|
||||||
- **Next.js App Router** —— 现代 React 框架
|
|
||||||
- **TypeScript** —— 类型安全
|
|
||||||
- **Tailwind CSS** —— 原子化样式
|
|
||||||
- **shadcn/ui** —— 精致组件库
|
|
||||||
- **Supabase** —— 后端服务
|
|
||||||
- **Stripe** —— 支付处理
|
|
||||||
|
|
||||||
这套组合是目前 AI IDE 最擅长的技术栈,也最符合现代 SaaS 的审美。
|
|
||||||
|
|
||||||
### 第一步:搭建项目骨架
|
|
||||||
|
|
||||||
把下面这段提示词丢给 Trae / Cursor / Claude Code:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我创建一个现代 SaaS 网站,名字叫 LaunchKit。
|
请基于当前 PRD,帮我生成一个 AI 营销文案 SaaS 的前端骨架。
|
||||||
|
|
||||||
技术栈要求:
|
|
||||||
- Next.js App Router
|
|
||||||
- TypeScript
|
|
||||||
- Tailwind CSS
|
|
||||||
- shadcn/ui
|
|
||||||
|
|
||||||
页面清单:
|
|
||||||
1. 首页 /
|
|
||||||
2. 登录页 /login
|
|
||||||
3. 注册页 /register
|
|
||||||
4. 用户工作台 /dashboard
|
|
||||||
5. 套餐页 /billing
|
|
||||||
6. 管理后台 /admin
|
|
||||||
|
|
||||||
请先只做前端结构,不接数据库。
|
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
- 首页要有现代 AI SaaS 落地页的气质
|
1. 分成三个入口:www、app、admin
|
||||||
- 登录和注册页保持简洁
|
2. 官网包括:首页、定价、FAQ
|
||||||
- Dashboard 左侧表单,右侧结果展示
|
3. app 包括:登录、注册、生成工作台、历史记录、套餐页
|
||||||
- Billing 页面展示 free 和 pro 两个套餐
|
4. admin 包括:后台首页、用户管理、生成记录、支付订单
|
||||||
- Admin 页面先做后台框架:侧边栏、顶部栏、表格区域
|
5. 先只生成页面结构和假数据,不接真实接口
|
||||||
- 使用 shadcn/ui 组件
|
6. 风格要像现代 SaaS,不像课堂 demo
|
||||||
- 页面风格要像真实产品,不要像课堂 demo
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第二步:完善工作台细节
|
然后再一块一块补:
|
||||||
|
|
||||||
|
- 鉴权
|
||||||
|
- 生成接口
|
||||||
|
- 数据库
|
||||||
|
- 支付
|
||||||
|
- 后台管理
|
||||||
|
|
||||||
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
|
每做完一个模块,至少检查这 5 件事:
|
||||||
|
|
||||||
|
| 检查项 | 要看什么 |
|
||||||
|
|------|------|
|
||||||
|
| 页面是否对 | 页面数量、入口、功能是否符合 PRD |
|
||||||
|
| 接口是否对 | 输入参数、返回结构、状态处理是否合理 |
|
||||||
|
| 权限是否对 | 游客、用户、管理员是否隔离 |
|
||||||
|
| 数据是否对 | 生成、历史、支付和套餐状态是否一致 |
|
||||||
|
| 演示是否对 | 是否真的能完整跑通注册、生成、升级这条链路 |
|
||||||
|
|
||||||
|
## 最后的预期效果
|
||||||
|
|
||||||
|
做完后,你应该拿到这些交付物:
|
||||||
|
|
||||||
|
- 一套可运行的 AI 文案 SaaS 项目
|
||||||
|
- 一份同级 PRD 文档
|
||||||
|
- 三套入口:`www / app / admin`
|
||||||
|
- 基础鉴权、生成、历史、支付、后台管理
|
||||||
|
- 一份 README
|
||||||
|
- 一个可以演示的线上版本或本地完整运行方案
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
| 维度 | 最低达标 |
|
||||||
|
|------|------|
|
||||||
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
|
| 产品闭环 | 注册、生成、历史、支付升级可以跑通 |
|
||||||
|
| 后台能力 | 用户、生成、支付数据可以查看 |
|
||||||
|
| 工程完整度 | 前端、后端、数据库、支付链路已接通 |
|
||||||
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
|
::: tip 🚀 完成后你会得到什么?
|
||||||
|
你得到的不只是一个生成页面,而是一套完整的 AI SaaS 开发过程样例。后面再做别的产品型项目,也可以继续沿用这套“先 PRD、再生成、再监工、再联调上线”的方法。
|
||||||
|
:::
|
||||||
|
|
||||||
第一版页面完成后,继续补充:
|
第一版页面完成后,继续补充:
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,442 @@
|
|||||||
|
# PRD:类 Dify 智能体编排平台
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:先把平台的 MVP 产品定义和实现边界写清楚,待 review 后再开发。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个模仿 Dify 核心体验的精简版智能体平台,重点不是复刻全部能力,而是跑通下面这条主链路:
|
||||||
|
|
||||||
|
- 创建智能体
|
||||||
|
- 配置 Prompt 与模型参数
|
||||||
|
- 发起对话
|
||||||
|
- 查看调用日志
|
||||||
|
- 可选接入知识库
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个类 Dify 的最小可用智能体编排平台。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
WWW["www.xxx.com<br/>官网前台"] --> API["应用 API / 管理 API"]
|
||||||
|
APP["app.xxx.com<br/>用户控制台"] --> API
|
||||||
|
ADMIN["admin.xxx.com<br/>后台管理台"] --> API
|
||||||
|
API --> AUTH["Supabase Auth"]
|
||||||
|
API --> DB["Supabase Postgres"]
|
||||||
|
API --> LLM["LLM Provider"]
|
||||||
|
API --> KB["知识库 / 文档处理"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.0 技术选型建议
|
||||||
|
|
||||||
|
- 前端框架:`Next.js App Router`
|
||||||
|
- 用户鉴权:`Supabase Auth`
|
||||||
|
- 数据库:`Supabase Postgres`
|
||||||
|
- 文件存储:`Supabase Storage`
|
||||||
|
- 模型层:统一后端适配层对接第三方 LLM
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 用户控制台:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.1 竞品参考(官方)
|
||||||
|
|
||||||
|
- [Dify](https://dify.ai/)
|
||||||
|
- [Dify Docs](https://docs.dify.ai/)
|
||||||
|
|
||||||
|
## 1.2 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考 Dify 的真实产品形态:
|
||||||
|
|
||||||
|
- 智能体管理、知识库、对话、日志应该是清晰分区,而不是混在一个页面里
|
||||||
|
- 配置页应该突出 Prompt、模型、参数和发布状态,而不是只给一个表单
|
||||||
|
- 对话页应该强调“当前正在使用哪个 agent”和“当前会话属于哪个 agent”
|
||||||
|
- 日志页应该能快速定位失败调用、耗时、token 消耗和错误原因
|
||||||
|
- 整体设计应更像 AI 平台控制台,而不是普通聊天网站
|
||||||
|
|
||||||
|
## 1.3 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `Dify` 控制台首页
|
||||||
|
- 重点看:应用列表、创建入口、最近活动、平台感导航
|
||||||
|
- `Dify` 应用配置页
|
||||||
|
- 重点看:Prompt、模型、参数、发布状态的组织方式
|
||||||
|
- `Dify` 知识库页
|
||||||
|
- 重点看:文档上传、状态、处理结果的管理方式
|
||||||
|
- `Dify` 调试 / 预览页
|
||||||
|
- 重点看:左侧配置、右侧运行结果的双栏思路
|
||||||
|
|
||||||
|
因此本项目的页面建议应更像平台控制台:
|
||||||
|
|
||||||
|
- 智能体列表页像应用市场/应用管理
|
||||||
|
- 配置页像控制台配置中心
|
||||||
|
- 对话页像调试与预览台
|
||||||
|
- 日志页像开发者运维页
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 想快速配置并测试多个智能体的开发者
|
||||||
|
- 想搭建内部知识助手的学生或独立开发者
|
||||||
|
- 需要查看模型调用记录的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 用户 5 分钟内创建第一个智能体
|
||||||
|
- 用户能在同一个平台里完成配置与对话
|
||||||
|
- 平台可以追踪每次调用的输入、输出、耗时与状态
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 注册/登录
|
||||||
|
- 智能体 CRUD
|
||||||
|
- 对话页
|
||||||
|
- 会话历史
|
||||||
|
- 调用日志页
|
||||||
|
- 可选知识库:仅支持文本文件上传与基础检索
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 复杂工作流节点编排 UI
|
||||||
|
- 多租户企业权限体系
|
||||||
|
- 工具调用沙箱
|
||||||
|
- 支付与计费
|
||||||
|
- 多模型路由策略
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 普通用户 | 管理自己的智能体、发起对话、看自己的日志 |
|
||||||
|
| 管理员 | 查看全平台用户和调用概览 |
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
## 5.1 页面架构总览
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,10 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 用户控制台 `7` 个大页面
|
||||||
|
- 后台管理台 `2` 个大页面
|
||||||
|
|
||||||
|
### A. 官网前台 `www.xxx.com`
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 产品介绍
|
||||||
|
- 能力说明
|
||||||
|
- 使用场景
|
||||||
|
- 注册/登录 CTA
|
||||||
|
|
||||||
|
### B. 用户控制台 `app.xxx.com`
|
||||||
|
|
||||||
|
#### 2. 登录页 `app:/login`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 登录
|
||||||
|
- 注册入口
|
||||||
|
- 第三方登录
|
||||||
|
|
||||||
|
#### 3. 智能体列表页 `app:/agents`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看所有智能体
|
||||||
|
- 新建智能体
|
||||||
|
- 编辑入口
|
||||||
|
- 状态筛选
|
||||||
|
|
||||||
|
#### 4. 智能体配置页 `app:/agents/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 配置名称和描述
|
||||||
|
- 配置 Prompt、模型、参数
|
||||||
|
- 启停和发布状态
|
||||||
|
|
||||||
|
#### 5. 对话页 `app:/chat`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 选择智能体
|
||||||
|
- 新建会话
|
||||||
|
- 聊天消息展示
|
||||||
|
- 问答发送与结果展示
|
||||||
|
|
||||||
|
#### 6. 会话详情页 `app:/chat/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看完整消息历史
|
||||||
|
- 重命名会话
|
||||||
|
- 继续提问
|
||||||
|
|
||||||
|
#### 7. 知识库页 `app:/knowledge`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 上传文档
|
||||||
|
- 查看处理状态
|
||||||
|
- 关联到智能体
|
||||||
|
|
||||||
|
#### 8. 日志页 `app:/logs`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看调用日志
|
||||||
|
- 按状态/模型筛选
|
||||||
|
- 查看错误详情
|
||||||
|
|
||||||
|
### C. 后台管理台 `admin.xxx.com`
|
||||||
|
|
||||||
|
#### 9. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 用户数
|
||||||
|
- 调用次数
|
||||||
|
- 失败率
|
||||||
|
- 平台资源概览
|
||||||
|
|
||||||
|
#### 10. 用户与调用概览页 `admin:/usage`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看用户使用情况
|
||||||
|
- 查看模型调用消耗
|
||||||
|
- 查看异常用户和高成本调用
|
||||||
|
|
||||||
|
## 5.2 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
user["用户"] --> login["登录"]
|
||||||
|
login --> agents["智能体列表页"]
|
||||||
|
agents --> config["配置智能体"]
|
||||||
|
config --> publish["保存配置"]
|
||||||
|
publish --> chat["对话页"]
|
||||||
|
chat --> logs["调用日志页"]
|
||||||
|
config --> kb["知识库页"]
|
||||||
|
kb --> chat
|
||||||
|
logs --> admin["后台调用概览"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 智能体:草稿 -> 已配置 -> 可用 / 停用
|
||||||
|
- 会话:新建 -> 进行中 -> 归档
|
||||||
|
- 文档:上传中 -> 处理中 -> 可检索 / 失败
|
||||||
|
- 调用:成功 / 错误 / 超时
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Next.js App Router
|
||||||
|
- TypeScript
|
||||||
|
- Tailwind CSS
|
||||||
|
- shadcn/ui
|
||||||
|
|
||||||
|
建议页面:
|
||||||
|
|
||||||
|
| 页面 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 登录页 | `/login` | 登录与注册 |
|
||||||
|
| 智能体列表 | `/agents` | 查看和管理智能体 |
|
||||||
|
| 智能体配置页 | `/agents/:id` | 编辑名称、Prompt、模型、温度等 |
|
||||||
|
| 对话页 | `/chat` | 左侧会话列表,右侧消息区 |
|
||||||
|
| 知识库页 | `/knowledge` | 上传资料、查看文档状态 |
|
||||||
|
| 日志页 | `/logs` | 查看模型调用日志 |
|
||||||
|
| 管理后台 | `/admin` | 用户数、调用数、失败数概览 |
|
||||||
|
|
||||||
|
前端核心组件:
|
||||||
|
|
||||||
|
- 智能体卡片列表
|
||||||
|
- Agent 配置表单
|
||||||
|
- 对话消息列表
|
||||||
|
- Prompt 调试面板
|
||||||
|
- 日志筛选表格
|
||||||
|
- 文件上传组件
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Node.js + NestJS 或 Express
|
||||||
|
- PostgreSQL / Supabase
|
||||||
|
- OpenAI 兼容接口
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `auth`
|
||||||
|
- `agents`
|
||||||
|
- `chat`
|
||||||
|
- `knowledge`
|
||||||
|
- `logs`
|
||||||
|
- `admin`
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
profiles (
|
||||||
|
id uuid primary key,
|
||||||
|
email text,
|
||||||
|
role text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
agents (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
name text,
|
||||||
|
description text,
|
||||||
|
system_prompt text,
|
||||||
|
model text,
|
||||||
|
temperature numeric,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
chat_sessions (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
agent_id uuid,
|
||||||
|
title text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
chat_messages (
|
||||||
|
id uuid primary key,
|
||||||
|
session_id uuid,
|
||||||
|
role text,
|
||||||
|
content text,
|
||||||
|
token_usage int,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
knowledge_documents (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
agent_id uuid,
|
||||||
|
filename text,
|
||||||
|
status text,
|
||||||
|
chunk_count int,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
run_logs (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
agent_id uuid,
|
||||||
|
session_id uuid,
|
||||||
|
model text,
|
||||||
|
latency_ms int,
|
||||||
|
prompt_tokens int,
|
||||||
|
completion_tokens int,
|
||||||
|
status text,
|
||||||
|
error_message text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 智能体总数
|
||||||
|
- 活跃用户数
|
||||||
|
- 日调用次数
|
||||||
|
- 平均响应耗时
|
||||||
|
- 模型调用失败率
|
||||||
|
- 知识库文档处理成功率
|
||||||
|
- 高消耗用户与高成本智能体
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- `/api/chat` 平均耗时与错误率
|
||||||
|
- 模型供应商调用成功率
|
||||||
|
- 知识库文档处理队列状态
|
||||||
|
- 数据库连接和日志写入健康状态
|
||||||
|
|
||||||
|
## 7. 功能清单
|
||||||
|
|
||||||
|
必须完成:
|
||||||
|
|
||||||
|
- 用户鉴权
|
||||||
|
- 创建/编辑/删除智能体
|
||||||
|
- 选择智能体发起会话
|
||||||
|
- 会话消息持久化
|
||||||
|
- 调用日志记录
|
||||||
|
|
||||||
|
第二优先级:
|
||||||
|
|
||||||
|
- 文档上传
|
||||||
|
- 基础检索增强
|
||||||
|
- 平台概览统计
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/auth/register` | 注册 |
|
||||||
|
| `POST` | `/api/auth/login` | 登录 |
|
||||||
|
| `GET` | `/api/agents` | 获取当前用户的智能体列表 |
|
||||||
|
| `POST` | `/api/agents` | 创建智能体 |
|
||||||
|
| `PATCH` | `/api/agents/:id` | 更新智能体配置 |
|
||||||
|
| `DELETE` | `/api/agents/:id` | 删除智能体 |
|
||||||
|
| `POST` | `/api/chat/sessions` | 创建新会话 |
|
||||||
|
| `POST` | `/api/chat/sessions/:id/messages` | 向某个会话发送消息 |
|
||||||
|
| `GET` | `/api/chat/sessions/:id/messages` | 获取会话消息 |
|
||||||
|
| `POST` | `/api/knowledge/documents` | 上传知识库文档 |
|
||||||
|
| `GET` | `/api/logs` | 获取调用日志 |
|
||||||
|
| `GET` | `/api/admin/overview` | 平台总览 |
|
||||||
|
|
||||||
|
`POST /api/chat/sessions/:id/messages` 请求示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"agentId": "agent_123",
|
||||||
|
"message": "帮我总结一下这个功能的定位"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. 关键业务规则
|
||||||
|
|
||||||
|
- 用户只能访问自己的智能体和会话
|
||||||
|
- 删除智能体前需要检查是否有活跃会话
|
||||||
|
- 日志中必须记录失败原因
|
||||||
|
- 知识库文档处理失败要可见
|
||||||
|
|
||||||
|
## 10. 非功能要求
|
||||||
|
|
||||||
|
- 用户只能访问自己的智能体、文档和会话
|
||||||
|
- 调用日志需要可追踪、可筛选
|
||||||
|
- 文档处理状态要有明确反馈
|
||||||
|
- 对话页在移动端至少可查看
|
||||||
|
- 智能体配置修改后要有变更提示
|
||||||
|
|
||||||
|
## 11. 开发顺序建议
|
||||||
|
|
||||||
|
1. 登录与基础鉴权
|
||||||
|
2. 智能体 CRUD
|
||||||
|
3. 对话页和会话存储
|
||||||
|
4. 日志记录
|
||||||
|
5. 文档上传与基础检索
|
||||||
|
6. 管理后台概览
|
||||||
|
|
||||||
|
## 12. 待确认项
|
||||||
|
|
||||||
|
- 第一版是否必须带知识库
|
||||||
|
- 模型供应商先只接 1 家还是预留多家
|
||||||
|
- 平台是否需要 Workspace 概念
|
||||||
|
- 日志是否保留完整 prompt 快照
|
||||||
@@ -1,223 +1,128 @@
|
|||||||
# 自制 Dify 智能体平台
|
# 类 Dify 智能体平台开发实战
|
||||||
|
|
||||||
如果你已经会用 Dify,下一步最值得挑战的不是“再配一个工作流”,而是自己做一个“类 Dify 平台”。
|
这个项目不是“再配一个聊天页”,而是围绕一份真实 PRD,把一个类 Dify 智能体平台从想法推进到可上线产品。
|
||||||
|
|
||||||
这个大作业会带你完成一个简化但完整的智能体平台:支持创建智能体、配置 Prompt、接知识库、发起对话、查看日志和调用统计。
|
你会同时看到三件事:
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
- 项目要做成什么
|
||||||
打造一个 **最小可用的智能体平台(Mini Dify)**。平台至少包含:智能体管理、会话问答、知识库接入(可选第一版简化)、调用记录与基础权限控制。目标是让用户能“创建一个智能体并真实对话”。
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
|
::: tip PRD 入口
|
||||||
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定能力边界', description: '先明确第一版做什么,不做什么' },
|
{ title: '看 PRD', description: '先明确页面、能力边界、鉴权、数据库和日志范围' },
|
||||||
{ title: '搭平台骨架', description: '完成前后端结构、鉴权与数据库设计' },
|
{ title: '生成骨架', description: '让 AI 先产出官网、控制台、后台三套界面骨架' },
|
||||||
{ title: '接智能体链路', description: '跑通创建智能体到对话返回的主流程' },
|
{ title: '监工迭代', description: '逐页验收、补接口、修权限、补知识库和日志链路' },
|
||||||
{ title: '上线交付', description: '补日志、文档、部署与演示材料' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的平台原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个题目值得做?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
因为它几乎覆盖了 AI 应用工程化的核心能力:
|
这是一个模仿 Dify 核心体验的智能体平台:
|
||||||
|
|
||||||
- 从“调用一个模型”升级到“管理多个智能体”
|
- 用户控制台:创建智能体、配置 Prompt、发起对话、查看日志
|
||||||
- 从“单页 Demo”升级到“有后台、有数据、有权限的平台”
|
- 平台后端:管理智能体、会话、消息、知识库和模型调用
|
||||||
- 从“能回答”升级到“可配置、可追踪、可维护”
|
- 管理后台:查看用户和平台资源使用情况
|
||||||
|
|
||||||
如果你未来想做 Agent 产品、企业知识助手或 AI SaaS,这个项目会是非常有含金量的一次训练。
|
## 开发过程怎么走?
|
||||||
|
|
||||||
## 先看全景:平台核心模块
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
|
先确认:
|
||||||
|
|
||||||
|
- 智能体、会话、日志、知识库哪些要进 MVP
|
||||||
|
- 页面和路由清单是否拍板
|
||||||
|
- 模型调用和日志记录边界是否清楚
|
||||||
|
- 多租户和复杂工作流是不是先不做
|
||||||
|
|
||||||
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
|
第一轮先生成:
|
||||||
|
|
||||||
|
- 登录页
|
||||||
|
- 智能体列表页
|
||||||
|
- 智能体配置页
|
||||||
|
- 对话页
|
||||||
|
- 日志页
|
||||||
|
- 知识库页
|
||||||
|
- 管理后台首页
|
||||||
|
|
||||||
|
### 3. 再进入“监工模式”
|
||||||
|
|
||||||
|
你要重点盯这几件事:
|
||||||
|
|
||||||
|
- 智能体是不是能被正确创建和编辑
|
||||||
|
- 对话是不是使用了正确的 agent 配置
|
||||||
|
- 会话和消息有没有稳定落库
|
||||||
|
- 日志是不是记录了耗时、token、错误
|
||||||
|
- 知识库和模型调用有没有串权限
|
||||||
|
|
||||||
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart TD
|
||||||
user["平台用户"] --> web["Web 控制台"]
|
prd["PRD"] --> app["用户控制台"]
|
||||||
web --> auth["登录与鉴权"]
|
prd --> admin["管理后台"]
|
||||||
web --> agent["智能体管理"]
|
app --> auth["鉴权"]
|
||||||
web --> chat["会话对话页"]
|
app --> agent["智能体配置"]
|
||||||
web --> logs["调用日志页"]
|
app --> chat["会话对话"]
|
||||||
agent --> api["后端 API"]
|
chat --> llm["模型调用"]
|
||||||
chat --> api
|
chat --> db["数据库"]
|
||||||
logs --> api
|
app --> kb["知识库接入"]
|
||||||
api --> db["PostgreSQL"]
|
admin --> logs["调用日志与平台概览"]
|
||||||
api --> llm["LLM Provider"]
|
logs --> db
|
||||||
api --> kb["知识库检索(可选第一版)"]
|
|
||||||
api --> trace["日志/成本统计"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
核心目标只有一个:用户能在后台创建智能体,然后在对话页选择该智能体并得到可追踪的回答。
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
## 1. 定能力边界:第一版先收住
|
|
||||||
|
|
||||||
### MVP 范围(建议)
|
|
||||||
|
|
||||||
- 用户注册/登录
|
|
||||||
- 智能体 CRUD(创建、编辑、启停、删除)
|
|
||||||
- 每个智能体可配置:名称、系统提示词、模型、温度
|
|
||||||
- 对话页可选择智能体进行聊天
|
|
||||||
- 记录每轮会话和调用日志
|
|
||||||
|
|
||||||
### 第一版暂不做
|
|
||||||
|
|
||||||
- 多租户复杂权限
|
|
||||||
- 复杂工作流编排器
|
|
||||||
- 工具调用沙箱
|
|
||||||
- 向量数据库高级检索策略
|
|
||||||
- 计费系统与支付闭环
|
|
||||||
|
|
||||||
### 角色与页面规划
|
|
||||||
|
|
||||||
| 角色 | 页面 | 核心动作 |
|
|
||||||
|------|------|------|
|
|
||||||
| 普通用户 | `/agents` | 创建/编辑自己的智能体 |
|
|
||||||
| 普通用户 | `/chat` | 选择智能体并发起对话 |
|
|
||||||
| 普通用户 | `/logs` | 查看调用记录和错误信息 |
|
|
||||||
| 管理员(可选) | `/admin/users` | 查看用户与资源使用情况 |
|
|
||||||
|
|
||||||
### 数据模型建议
|
|
||||||
|
|
||||||
```sql
|
|
||||||
profiles (
|
|
||||||
id uuid primary key,
|
|
||||||
email text,
|
|
||||||
role text, -- user / admin
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
agents (
|
|
||||||
id uuid primary key,
|
|
||||||
user_id uuid,
|
|
||||||
name text,
|
|
||||||
system_prompt text,
|
|
||||||
model text,
|
|
||||||
temperature numeric,
|
|
||||||
status text, -- active / inactive
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
conversations (
|
|
||||||
id uuid primary key,
|
|
||||||
user_id uuid,
|
|
||||||
agent_id uuid,
|
|
||||||
title text,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
messages (
|
|
||||||
id uuid primary key,
|
|
||||||
conversation_id uuid,
|
|
||||||
role text, -- user / assistant
|
|
||||||
content text,
|
|
||||||
token_usage int,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
llm_logs (
|
|
||||||
id uuid primary key,
|
|
||||||
user_id uuid,
|
|
||||||
agent_id uuid,
|
|
||||||
model text,
|
|
||||||
latency_ms int,
|
|
||||||
prompt_tokens int,
|
|
||||||
completion_tokens int,
|
|
||||||
status text, -- success / error
|
|
||||||
error_message text,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. 搭平台骨架:前后端先跑起来
|
|
||||||
|
|
||||||
### 推荐技术栈
|
|
||||||
|
|
||||||
- **Next.js App Router**(前端 + 部分 BFF)
|
|
||||||
- **TypeScript**
|
|
||||||
- **Tailwind CSS + shadcn/ui**
|
|
||||||
- **Node.js + Express/NestJS**(如你想分离后端)
|
|
||||||
- **PostgreSQL / Supabase**
|
|
||||||
- **OpenAI / 兼容 OpenAI 协议模型接口**
|
|
||||||
|
|
||||||
### 第一步:让 AI IDE 先搭骨架
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我创建一个 Mini Dify 平台骨架(Next.js + TypeScript + Tailwind)。
|
请基于当前 PRD,帮我生成一个类 Dify 智能体平台的前端骨架。
|
||||||
|
|
||||||
页面要求:
|
|
||||||
1. /login 登录页
|
|
||||||
2. /agents 智能体管理页(列表 + 新建弹窗)
|
|
||||||
3. /chat 对话页(左侧会话列表 + 右侧聊天区)
|
|
||||||
4. /logs 调用日志页(表格 + 状态筛选)
|
|
||||||
|
|
||||||
后端要求:
|
|
||||||
- 提供 /api/agents、/api/chat、/api/logs 的基础接口
|
|
||||||
- 所有接口只允许登录用户访问
|
|
||||||
|
|
||||||
先用 mock 数据跑通页面交互,再补真实数据库。
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第二步:补鉴权与数据库
|
|
||||||
|
|
||||||
你可以继续让 AI IDE 分步骤落地:
|
|
||||||
|
|
||||||
```text
|
|
||||||
请把我当成 0 基础,带我完成 Mini Dify 的鉴权和数据库接入。
|
|
||||||
|
|
||||||
目标:
|
|
||||||
1. 用户可以注册、登录、退出
|
|
||||||
2. 登录后才能访问 /agents、/chat、/logs
|
|
||||||
3. 创建 agents 表并实现新增/查询
|
|
||||||
4. 只有 agent 所有者可编辑自己的 agent
|
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
- 说明每步修改了哪些文件
|
1. 用户侧包括:登录、智能体列表、智能体配置、对话页、日志页、知识库页
|
||||||
- 明确需要在数据库后台操作的 SQL
|
2. 后台侧包括:后台首页、用户概览、资源使用概览
|
||||||
- 完成后给我一份验证清单
|
3. 先只生成页面结构和假数据,不接真实接口
|
||||||
|
4. 风格要像现代 AI 平台
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. 接智能体主链路:从“创建”到“回答”
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
### 智能体调用时序图
|
| 检查项 | 要看什么 |
|
||||||
|
|------|------|
|
||||||
|
| 页面是否对 | 页面数量、功能是否符合 PRD |
|
||||||
|
| 接口是否对 | agents、chat、logs、knowledge 是否闭环 |
|
||||||
|
| 权限是否对 | 用户是否只能管理自己的 agent 和会话 |
|
||||||
|
| 数据是否对 | messages、logs、documents 是否一致 |
|
||||||
|
| 演示是否对 | 是否能演示“创建 agent -> 对话 -> 查看日志”完整链路 |
|
||||||
|
|
||||||
```mermaid
|
## 最后的预期效果
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
actor U as 用户
|
|
||||||
participant FE as 前端对话页
|
|
||||||
participant API as 后端 /api/chat
|
|
||||||
participant DB as 数据库
|
|
||||||
participant LLM as 模型服务
|
|
||||||
|
|
||||||
U->>FE: 选择智能体并发送问题
|
- 一套可运行的类 Dify 平台
|
||||||
FE->>API: POST /api/chat {agentId, message}
|
- 一份同级 PRD 文档
|
||||||
API->>DB: 读取 agent 配置与历史消息
|
- 用户侧控制台 + 管理后台
|
||||||
API->>LLM: 组装 system prompt + 历史上下文
|
- 智能体、对话、日志、知识库基础能力
|
||||||
LLM-->>API: 返回回答
|
- README 和演示方案
|
||||||
API->>DB: 保存 user/assistant 消息 + 日志
|
|
||||||
API-->>FE: 返回回答内容
|
|
||||||
FE-->>U: 渲染回复
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第三步:实现聊天接口(最小版本)
|
## 验收标准
|
||||||
|
|
||||||
第一版聊天接口建议做到:
|
| 维度 | 最低达标 |
|
||||||
|
|------|------|
|
||||||
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
|
| 产品闭环 | 创建 agent、发起对话、查看日志可以跑通 |
|
||||||
|
| 后台能力 | 用户与平台使用概览可查看 |
|
||||||
|
| 工程完整度 | 前端、后端、数据库、模型调用链路已接通 |
|
||||||
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
- 接收 `agentId` 和用户输入
|
::: tip 🚀 完成后你会得到什么?
|
||||||
- 根据 `agentId` 加载对应系统提示词
|
你得到的不只是一个聊天页,而是一套 AI 平台型产品的开发样例。后面做知识助手、企业 Agent、AI 控制台时,都可以继续复用这套方法。
|
||||||
- 调用模型并返回结果
|
:::
|
||||||
- 将问答落库到 `messages`
|
|
||||||
- 将耗时/状态写入 `llm_logs`
|
|
||||||
|
|
||||||
提示词示例:
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我实现 /api/chat 接口。
|
|
||||||
|
|
||||||
业务规则:
|
|
||||||
1. 必须校验用户是否已登录
|
|
||||||
2. 必须校验 agent 属于当前用户
|
|
||||||
3. 请求体包含 agentId 和 message
|
|
||||||
4. 调用 LLM 前拼接系统提示词和最近 10 条上下文
|
4. 调用 LLM 前拼接系统提示词和最近 10 条上下文
|
||||||
5. 返回 assistant 内容并写入消息表
|
5. 返回 assistant 内容并写入消息表
|
||||||
6. 无论成功失败都写一条 llm_logs
|
6. 无论成功失败都写一条 llm_logs
|
||||||
|
|||||||
@@ -0,0 +1,356 @@
|
|||||||
|
# PRD:在线考试与管理系统
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:先明确角色、考试链路、后台管理和核心数据模型,再进入开发。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个典型的多角色业务系统。它不只是答题页面,而是一整套包含学生端、管理端、题库、考试、提交记录和成绩处理的产品。
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个支持学生答题、管理员出卷、题库维护、成绩统计和后台管理的在线考试系统。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
HOME["www.xxx.com<br/>官网前台"] --> API["应用 API / 管理 API"]
|
||||||
|
STUDENT["app.xxx.com<br/>学生端"] --> API
|
||||||
|
ADMIN["admin.xxx.com<br/>管理后台"] --> API
|
||||||
|
API --> AUTH["JWT / Session Auth"]
|
||||||
|
API --> DB["PostgreSQL"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.1 技术选型建议
|
||||||
|
|
||||||
|
- 前端框架:`Next.js` 或 `React + Vite`
|
||||||
|
- 后端框架:`Node.js + Express`
|
||||||
|
- 数据库:`PostgreSQL`
|
||||||
|
- 鉴权:`JWT + Role-based Access Control`
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 学生端:`app.xxx.com`
|
||||||
|
- 管理后台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.2 竞品参考(官方)
|
||||||
|
|
||||||
|
- [Canvas by Instructure](https://www.instructure.com/canvas)
|
||||||
|
- [Moodle LMS](https://moodle.com/products/lms/)
|
||||||
|
|
||||||
|
## 1.3 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考这些真实教学产品:
|
||||||
|
|
||||||
|
- 借鉴 `Canvas` 的信息分层:学生端和管理端职责清晰,不把所有功能放在同一个视图
|
||||||
|
- 借鉴 `Moodle` 的题库与考试管理思路:题目、考试、提交、成绩应是独立模块
|
||||||
|
- 学生侧页面应强调“考试状态、剩余时间、提交反馈”
|
||||||
|
- 管理端页面应强调“题库维护、考试发布、提交记录、统计面板”
|
||||||
|
- 设计上应更像真实 LMS/考试平台,而不是单一答题表单
|
||||||
|
|
||||||
|
## 1.4 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `Canvas` 的课程/作业/测验组织方式
|
||||||
|
- 重点看:学生如何看到待完成事项、任务状态和结果反馈
|
||||||
|
- `Moodle` 的题库与测验页
|
||||||
|
- 重点看:题目、测验、提交记录这些模块如何拆开
|
||||||
|
- `Moodle` 的后台管理体验
|
||||||
|
- 重点看:题库管理、测验配置、成绩查看如何层次化呈现
|
||||||
|
|
||||||
|
因此本项目建议页面遵循:
|
||||||
|
|
||||||
|
- 学生端强调“流程感”
|
||||||
|
- 管理端强调“配置感”
|
||||||
|
- 成绩页强调“结果感”
|
||||||
|
- 后台首页强调“概览感”
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 参加考试和查看成绩的学生
|
||||||
|
- 维护考试、题目、成绩和统计的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 学生能顺利完成考试流程
|
||||||
|
- 管理员能完成题库、考试和提交记录管理
|
||||||
|
- 系统能稳定保存提交结果和成绩统计
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 登录
|
||||||
|
- 学生考试列表
|
||||||
|
- 学生答题页
|
||||||
|
- 提交结果与历史成绩
|
||||||
|
- 管理后台
|
||||||
|
- 题库管理
|
||||||
|
- 考试管理
|
||||||
|
- 提交记录与成绩查看
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 随机组卷
|
||||||
|
- 复杂防作弊
|
||||||
|
- 多校区多租户
|
||||||
|
- 监考视频
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 学生 | 查看考试、开始答题、提交试卷、查看成绩 |
|
||||||
|
| 管理员 | 管理题库、考试、提交记录和成绩统计 |
|
||||||
|
|
||||||
|
## 5. 页面架构
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,10 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 学生端 `4` 个大页面
|
||||||
|
- 管理后台 `5` 个大页面
|
||||||
|
|
||||||
|
### 官网前台
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 平台介绍
|
||||||
|
- 登录入口
|
||||||
|
- 考试说明
|
||||||
|
|
||||||
|
### 学生端
|
||||||
|
|
||||||
|
#### 2. 登录页 `app:/login`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 账号密码登录
|
||||||
|
- 找回密码入口
|
||||||
|
|
||||||
|
#### 3. 考试列表页 `app:/student/exams`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看可参加考试
|
||||||
|
- 查看考试状态与时间
|
||||||
|
- 进入考试
|
||||||
|
|
||||||
|
#### 4. 答题页 `app:/student/exams/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 展示题目
|
||||||
|
- 作答
|
||||||
|
- 倒计时
|
||||||
|
- 提交试卷
|
||||||
|
|
||||||
|
#### 5. 历史成绩页 `app:/student/history`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看历史考试
|
||||||
|
- 查看成绩与状态
|
||||||
|
- 查看待复核情况
|
||||||
|
|
||||||
|
### 管理后台
|
||||||
|
|
||||||
|
#### 6. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 考试总数
|
||||||
|
- 学生提交数
|
||||||
|
- 待批改数
|
||||||
|
- 成绩概览
|
||||||
|
|
||||||
|
#### 7. 题库管理 `admin:/questions`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 新增题目
|
||||||
|
- 编辑题目
|
||||||
|
- 分类筛选
|
||||||
|
- 批量导入
|
||||||
|
|
||||||
|
#### 8. 考试管理 `admin:/exams`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 创建考试
|
||||||
|
- 绑定题目
|
||||||
|
- 设置开始时间和时长
|
||||||
|
- 发布/关闭考试
|
||||||
|
|
||||||
|
#### 9. 提交记录 `admin:/submissions`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看学生提交
|
||||||
|
- 查看答案详情
|
||||||
|
- 人工复核
|
||||||
|
|
||||||
|
#### 10. 成绩统计 `admin:/scores`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看考试平均分
|
||||||
|
- 查看通过率
|
||||||
|
- 查看题目错误率
|
||||||
|
|
||||||
|
## 5.1 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
student["学生"] --> login["登录"]
|
||||||
|
login --> list["考试列表"]
|
||||||
|
list --> start["开始考试"]
|
||||||
|
start --> answer["答题页"]
|
||||||
|
answer --> submit["提交试卷"]
|
||||||
|
submit --> score["成绩结果 / 待复核"]
|
||||||
|
admin["管理员"] --> bank["题库管理"]
|
||||||
|
bank --> exam["考试管理"]
|
||||||
|
exam --> publish["发布考试"]
|
||||||
|
publish --> list
|
||||||
|
submit --> review["提交记录"]
|
||||||
|
review --> scoreAdmin["成绩统计"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 考试:草稿 -> 已发布 -> 已关闭
|
||||||
|
- 提交:进行中 -> 已提交 -> 已评阅 / 待复核
|
||||||
|
- 学生成绩:未出分 -> 已出分
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `auth`
|
||||||
|
- `exams`
|
||||||
|
- `questions`
|
||||||
|
- `submissions`
|
||||||
|
- `scores`
|
||||||
|
- `admin`
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
profiles (
|
||||||
|
id uuid primary key,
|
||||||
|
email text,
|
||||||
|
role text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
exams (
|
||||||
|
id uuid primary key,
|
||||||
|
title text,
|
||||||
|
description text,
|
||||||
|
duration_minutes int,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
questions (
|
||||||
|
id uuid primary key,
|
||||||
|
type text,
|
||||||
|
stem text,
|
||||||
|
options jsonb,
|
||||||
|
correct_answer text,
|
||||||
|
score int,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
submissions (
|
||||||
|
id uuid primary key,
|
||||||
|
exam_id uuid,
|
||||||
|
student_id uuid,
|
||||||
|
status text,
|
||||||
|
total_score numeric,
|
||||||
|
submitted_at timestamptz
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 已发布考试数
|
||||||
|
- 已参加人数
|
||||||
|
- 提交率
|
||||||
|
- 平均分 / 通过率
|
||||||
|
- 待复核题目数
|
||||||
|
- 题目错误率 Top10
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- 登录成功率
|
||||||
|
- 提交流程错误率
|
||||||
|
- 自动判分耗时
|
||||||
|
- 数据库写入失败率
|
||||||
|
|
||||||
|
## 7. 功能清单
|
||||||
|
|
||||||
|
必须完成:
|
||||||
|
|
||||||
|
- 登录与角色鉴权
|
||||||
|
- 学生考试列表
|
||||||
|
- 学生答题与提交
|
||||||
|
- 历史成绩查看
|
||||||
|
- 题库管理
|
||||||
|
- 考试管理
|
||||||
|
- 提交记录查看
|
||||||
|
- 成绩统计查看
|
||||||
|
|
||||||
|
可选增强:
|
||||||
|
|
||||||
|
- 随机组卷
|
||||||
|
- 批量导题
|
||||||
|
- 班级维度统计
|
||||||
|
- 成绩导出
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/auth/login` | 登录 |
|
||||||
|
| `GET` | `/api/exams` | 获取学生可见考试列表 |
|
||||||
|
| `GET` | `/api/exams/:id` | 获取考试详情 |
|
||||||
|
| `POST` | `/api/submissions/start` | 开始考试 |
|
||||||
|
| `POST` | `/api/submissions/:id/submit` | 提交试卷 |
|
||||||
|
| `GET` | `/api/student/history` | 获取历史成绩 |
|
||||||
|
| `GET` | `/api/admin/questions` | 获取题库 |
|
||||||
|
| `POST` | `/api/admin/questions` | 新增题目 |
|
||||||
|
| `GET` | `/api/admin/exams` | 获取考试列表 |
|
||||||
|
| `POST` | `/api/admin/exams` | 创建考试 |
|
||||||
|
| `GET` | `/api/admin/submissions` | 获取提交记录 |
|
||||||
|
| `GET` | `/api/admin/scores` | 获取成绩统计 |
|
||||||
|
|
||||||
|
## 9. 非功能要求
|
||||||
|
|
||||||
|
- 学生端和管理员端权限必须严格隔离
|
||||||
|
- 交卷后成绩和答题记录需稳定落库
|
||||||
|
- 自动判分与人工复核状态要清晰
|
||||||
|
- 后台统计口径要保持一致
|
||||||
|
- 答题页在倒计时和断网提示上要有明确反馈
|
||||||
|
|
||||||
|
## 10. 开发顺序建议
|
||||||
|
|
||||||
|
1. 登录与角色鉴权
|
||||||
|
2. 学生端考试列表和答题页
|
||||||
|
3. 提交与成绩链路
|
||||||
|
4. 管理后台题库和考试管理
|
||||||
|
5. 提交记录和统计页
|
||||||
|
|
||||||
|
## 11. 待确认项
|
||||||
|
|
||||||
|
- 第一版是否只支持单选/判断/简答
|
||||||
|
- 简答题是否只做人工复核
|
||||||
|
- 是否要限制考试只能提交一次
|
||||||
@@ -1,222 +1,161 @@
|
|||||||
# 大作业 2:在线考试与管理系统
|
# 在线考试与管理系统开发实战
|
||||||
|
|
||||||
做完第一个 SaaS 项目后,下一步不只是“再做一个网站”,而是要进入更接近真实业务系统的场景。
|
这个项目不是单纯的答题页面,而是围绕一份真实 PRD,把一个多角色业务系统从想法推进到可上线产品。
|
||||||
|
|
||||||
在线考试系统就是一个很典型的练手题:
|
你会同时看到三件事:
|
||||||
|
|
||||||
- 前台不再只有一个工作台,而是有 **学生端完整考试流程**
|
- 项目要做成什么
|
||||||
- 后台不再只是看数据,而是要有 **题库管理、考试管理、成绩管理**
|
- 如何基于 PRD 拆解并推进开发
|
||||||
- 权限不再只是“登录/未登录”,而是要处理 **学生 / 管理员** 两种角色
|
- 最后应该交付出什么样的效果
|
||||||
- 数据也不再是一张结果表,而是会涉及 **考试、题目、答卷、成绩、用户** 多种实体
|
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
::: tip PRD 入口
|
||||||
打造一个 **在线考试与管理系统**。学生登录后可查看考试列表、开始答题、提交试卷、查看历史成绩;管理员可以创建考试、维护题库、查看提交记录,并根据题目规则完成自动判分或人工复核。
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定角色与范围', description: '先把参与者、页面和数据模型定下来' },
|
{ title: '看 PRD', description: '先明确角色、页面、考试链路、题库和成绩范围' },
|
||||||
{ title: '搭前台', description: '学生端和管理端页面骨架先跑起来' },
|
{ title: '生成骨架', description: '让 AI 先产出官网、学生端、管理后台三套界面骨架' },
|
||||||
{ title: '写接口', description: '用 Express 接通登录、考试、提交、批改' },
|
{ title: '监工迭代', description: '逐页验收、补接口、修权限、打通考试与成绩链路' },
|
||||||
{ title: '上线交付', description: '部署、README、演示材料全部补齐' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的系统原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个题目值得做?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
因为它特别适合练“业务系统思维”。
|
这是一个典型的在线考试与管理系统:
|
||||||
|
|
||||||
你会发现,考试系统不是把几个页面摆在一起就结束了,它必须处理很多真实约束:
|
- 官网前台:负责平台介绍和登录入口
|
||||||
|
- 学生端:负责考试列表、答题、提交和成绩查看
|
||||||
|
- 管理后台:负责题库、考试、提交记录和成绩统计
|
||||||
|
|
||||||
- 学生只能看到自己该看的考试和成绩
|
后端需要接住这些关键能力:
|
||||||
- 管理员要能发布考试、维护题目、查看提交情况
|
|
||||||
- 一场考试通常会有开始时间、结束时间、作答时长、是否允许重复提交等规则
|
|
||||||
- 题目可能有单选、多选、判断、简答,不同题型的判分方式也不一样
|
|
||||||
|
|
||||||
这些问题会逼着你第一次认真面对:
|
- 登录鉴权
|
||||||
|
- 角色权限
|
||||||
|
- 考试和题库管理
|
||||||
|
- 提交流程与自动判分
|
||||||
|
- 成绩和统计管理
|
||||||
|
|
||||||
- **角色权限**
|
## 开发过程怎么走?
|
||||||
- **数据建模**
|
|
||||||
- **接口设计**
|
|
||||||
- **提交流程与状态流转**
|
|
||||||
|
|
||||||
这正是从“会写页面”到“会做系统”的关键一步。
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
## 先看全景:这个系统到底由哪些部分组成?
|
先确认:
|
||||||
|
|
||||||
|
- 角色是不是只收敛到 `student / admin`
|
||||||
|
- 页面清单是否完整
|
||||||
|
- 题型、提交流程和批改范围是否拍板
|
||||||
|
- 接口与数据表是否合理
|
||||||
|
|
||||||
|
如果 PRD 没拍板,就先不要写代码。
|
||||||
|
|
||||||
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
|
第一轮先生成:
|
||||||
|
|
||||||
|
- 登录页
|
||||||
|
- 学生考试列表
|
||||||
|
- 学生答题页
|
||||||
|
- 学生成绩页
|
||||||
|
- 后台首页
|
||||||
|
- 题库管理页
|
||||||
|
- 考试管理页
|
||||||
|
- 提交记录页
|
||||||
|
- 成绩统计页
|
||||||
|
|
||||||
|
先把页面结构、导航和信息架构搭出来。
|
||||||
|
|
||||||
|
### 3. 再进入“监工模式”
|
||||||
|
|
||||||
|
你要重点盯这几件事:
|
||||||
|
|
||||||
|
- 学生和管理员入口有没有分清
|
||||||
|
- 登录后权限是不是隔离
|
||||||
|
- 开始考试、作答、提交链路是不是闭环
|
||||||
|
- 自动判分和人工复核边界是不是清楚
|
||||||
|
- 管理端能不能看到真实提交记录和成绩统计
|
||||||
|
|
||||||
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
student["学生"] --> studentPages["学生端页面"]
|
prd["PRD"] --> web["官网前台"]
|
||||||
admin["管理员"] --> adminPages["管理端页面"]
|
prd --> student["学生端"]
|
||||||
studentPages --> auth["登录鉴权"]
|
prd --> admin["管理后台"]
|
||||||
adminPages --> auth
|
student --> auth["鉴权"]
|
||||||
studentPages --> api["Express API"]
|
student --> exam["考试与作答"]
|
||||||
adminPages --> api
|
exam --> db["数据库"]
|
||||||
api --> exam["exams / questions"]
|
admin --> question["题库管理"]
|
||||||
api --> submission["submissions / answers"]
|
admin --> submission["提交记录与成绩统计"]
|
||||||
api --> profile["users / profiles"]
|
question --> db
|
||||||
api --> grading["自动判分 / 结果计算"]
|
submission --> db
|
||||||
grading --> score["scores / 统计"]
|
|
||||||
score --> studentPages
|
|
||||||
score --> adminPages
|
|
||||||
```
|
```
|
||||||
|
|
||||||
你最终要交付的,不是一套静态页面,而是一套能让两类角色都跑通核心业务的系统。
|
只要这条链路能跑通,这个项目就不是课堂作业,而是一套完整的业务系统原型。
|
||||||
|
|
||||||
## 1. 定角色与范围:先把“做什么”说清楚
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
### 角色设计
|
推荐按模块逐步下指令,而不是一句“帮我做完”。
|
||||||
|
|
||||||
这次只保留两种角色,先把范围收住:
|
|
||||||
|
|
||||||
| 角色 | 核心动作 |
|
|
||||||
|------|------|
|
|
||||||
| 学生 | 登录、查看考试列表、开始答题、提交试卷、查看历史成绩 |
|
|
||||||
| 管理员 | 登录、创建考试、维护题库、查看提交记录、查看成绩统计 |
|
|
||||||
|
|
||||||
### 核心页面规划
|
|
||||||
|
|
||||||
按下面这些页面来做,已经足够覆盖主要能力:
|
|
||||||
|
|
||||||
| 页面 | 路径 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| 首页 | `/` | 说明平台用途,提供登录入口 |
|
|
||||||
| 登录页 | `/login` | 学生和管理员共用登录入口 |
|
|
||||||
| 学生考试列表 | `/student/exams` | 展示可参加的考试和状态 |
|
|
||||||
| 学生答题页 | `/student/exams/:id` | 显示题目、倒计时、提交按钮 |
|
|
||||||
| 学生成绩页 | `/student/history` | 查看历史考试记录和分数 |
|
|
||||||
| 管理后台首页 | `/admin` | 后台概览与导航 |
|
|
||||||
| 考试管理 | `/admin/exams` | 创建、发布、下线考试 |
|
|
||||||
| 题库管理 | `/admin/questions` | 新增和编辑题目 |
|
|
||||||
| 提交记录 | `/admin/submissions` | 查看学生提交和判分结果 |
|
|
||||||
|
|
||||||
### 建议先做的业务边界
|
|
||||||
|
|
||||||
为了确保你能完成,第一版建议只做这些:
|
|
||||||
|
|
||||||
- 题型先支持 **单选、判断、简答** 三种
|
|
||||||
- 自动判分先覆盖 **单选、判断**
|
|
||||||
- 简答题先做 **人工复核**,或者展示“待批改”
|
|
||||||
- 每场考试先只允许 **提交一次**
|
|
||||||
- 不做复杂防作弊,不做随机组卷,不做监考录像
|
|
||||||
|
|
||||||
### 数据模型
|
|
||||||
|
|
||||||
推荐至少有下面这几张表:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
profiles (
|
|
||||||
id uuid primary key,
|
|
||||||
email text,
|
|
||||||
role text, -- student / admin
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
exams (
|
|
||||||
id uuid primary key,
|
|
||||||
title text,
|
|
||||||
description text,
|
|
||||||
duration_minutes int,
|
|
||||||
status text, -- draft / published / closed
|
|
||||||
created_by uuid,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
questions (
|
|
||||||
id uuid primary key,
|
|
||||||
type text, -- single / judge / short
|
|
||||||
stem text,
|
|
||||||
options jsonb,
|
|
||||||
correct_answer text,
|
|
||||||
score int,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
exam_questions (
|
|
||||||
id uuid primary key,
|
|
||||||
exam_id uuid,
|
|
||||||
question_id uuid,
|
|
||||||
sort_order int
|
|
||||||
)
|
|
||||||
|
|
||||||
submissions (
|
|
||||||
id uuid primary key,
|
|
||||||
exam_id uuid,
|
|
||||||
student_id uuid,
|
|
||||||
status text, -- in_progress / submitted / reviewed
|
|
||||||
total_score numeric,
|
|
||||||
submitted_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
submission_answers (
|
|
||||||
id uuid primary key,
|
|
||||||
submission_id uuid,
|
|
||||||
question_id uuid,
|
|
||||||
answer_text text,
|
|
||||||
is_correct boolean,
|
|
||||||
score numeric
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 关键时序图
|
|
||||||
|
|
||||||
学生参加考试时,系统的主链路大致长这样:
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
actor Student as 学生
|
|
||||||
participant Frontend as 学生端页面
|
|
||||||
participant API as Express API
|
|
||||||
participant DB as 数据库
|
|
||||||
|
|
||||||
Student->>Frontend: 进入考试列表页
|
|
||||||
Frontend->>API: GET /api/exams
|
|
||||||
API->>DB: 查询已发布考试
|
|
||||||
DB-->>API: 返回考试列表
|
|
||||||
API-->>Frontend: 返回可参加考试
|
|
||||||
Student->>Frontend: 点击开始考试
|
|
||||||
Frontend->>API: POST /api/submissions/start
|
|
||||||
API->>DB: 创建 submission
|
|
||||||
API-->>Frontend: 返回试卷与 submissionId
|
|
||||||
Student->>Frontend: 作答并提交
|
|
||||||
Frontend->>API: POST /api/submissions/:id/submit
|
|
||||||
API->>API: 自动判分客观题
|
|
||||||
API->>DB: 保存答案与总分
|
|
||||||
API-->>Frontend: 返回提交结果
|
|
||||||
```
|
|
||||||
|
|
||||||
到这一步,你应该已经能看清这个作业的真正重点了:不是“页面多”,而是“状态和数据流更多”。
|
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
|
||||||
<ClientOnly>
|
|
||||||
<StepBar :active="1" :items="[
|
|
||||||
{ title: '定角色与范围', description: '先把参与者、页面和数据模型定下来' },
|
|
||||||
{ title: '搭前台', description: '学生端和管理端页面骨架先跑起来' },
|
|
||||||
{ title: '写接口', description: '用 Express 接通登录、考试、提交、批改' },
|
|
||||||
{ title: '上线交付', description: '部署、README、演示材料全部补齐' }
|
|
||||||
]" />
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 2. 搭前台:先让学生端和管理端“看得见、点得动”
|
|
||||||
|
|
||||||
这一步先不要急着把所有后端写完,先把页面骨架搭出来。
|
|
||||||
|
|
||||||
### 推荐技术栈
|
|
||||||
|
|
||||||
- **Next.js / React**:负责前端页面
|
|
||||||
- **TypeScript**:保证类型清晰
|
|
||||||
- **Tailwind CSS + shadcn/ui**:快速搭建专业界面
|
|
||||||
- **Express**:编写 REST API
|
|
||||||
- **PostgreSQL / Supabase Postgres**:存业务数据
|
|
||||||
|
|
||||||
### 第一步:让 AI IDE 先帮你起出页面骨架
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我创建一个在线考试与管理系统的前端页面骨架。
|
请基于当前 PRD,帮我生成一个在线考试与管理系统的前端骨架。
|
||||||
|
|
||||||
|
要求:
|
||||||
|
1. 分成三个入口:www、app、admin
|
||||||
|
2. 官网包括:首页、登录入口
|
||||||
|
3. 学生端包括:登录、考试列表、答题页、历史成绩
|
||||||
|
4. 后台包括:后台首页、题库管理、考试管理、提交记录、成绩统计
|
||||||
|
5. 先只生成页面结构和假数据,不接真实接口
|
||||||
|
6. 风格要像真实业务系统,不像课堂 demo
|
||||||
|
```
|
||||||
|
|
||||||
|
然后再一块一块补:
|
||||||
|
|
||||||
|
- 登录鉴权
|
||||||
|
- 考试接口
|
||||||
|
- 提交与判分
|
||||||
|
- 题库管理
|
||||||
|
- 成绩统计
|
||||||
|
|
||||||
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
|
每做完一个模块,至少检查这 5 件事:
|
||||||
|
|
||||||
|
| 检查项 | 要看什么 |
|
||||||
|
|------|------|
|
||||||
|
| 页面是否对 | 页面数量、入口、功能是否符合 PRD |
|
||||||
|
| 接口是否对 | 请求参数、返回结构、状态处理是否合理 |
|
||||||
|
| 权限是否对 | 学生和管理员权限是否隔离 |
|
||||||
|
| 数据是否对 | 题目、提交、成绩、统计是否一致 |
|
||||||
|
| 演示是否对 | 是否真的能演示完整考试闭环 |
|
||||||
|
|
||||||
|
## 最后的预期效果
|
||||||
|
|
||||||
|
做完后,你应该拿到这些交付物:
|
||||||
|
|
||||||
|
- 一套可运行的在线考试系统项目
|
||||||
|
- 一份同级 PRD 文档
|
||||||
|
- 三套入口:`www / app / admin`
|
||||||
|
- 登录、题库、考试、提交、成绩、后台管理
|
||||||
|
- 一份 README
|
||||||
|
- 一个可以演示的线上版本或本地完整运行方案
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
| 维度 | 最低达标 |
|
||||||
|
|------|------|
|
||||||
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
|
| 产品闭环 | 登录、考试、提交、成绩查看可以跑通 |
|
||||||
|
| 后台能力 | 题库、考试、提交、成绩统计可以查看 |
|
||||||
|
| 工程完整度 | 前端、后端、数据库、判分链路已接通 |
|
||||||
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
|
::: tip 🚀 完成后你会得到什么?
|
||||||
|
你得到的不只是几个业务页面,而是一套完整的多角色系统开发样例。后面做教培、后台管理、内容平台项目时,都可以继续复用这套方法。
|
||||||
|
:::
|
||||||
|
|
||||||
技术栈要求:
|
技术栈要求:
|
||||||
- Next.js App Router
|
- Next.js App Router
|
||||||
|
|||||||
@@ -0,0 +1,758 @@
|
|||||||
|
# PRD:现代 AI 生图 SaaS 平台
|
||||||
|
|
||||||
|
状态:Draft v0.2
|
||||||
|
目标:先完成可 review 的产品与实现方案,不进入开发。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个现代化 AI 生图 SaaS 网站,产品体验参考 Midjourney、Leonardo、Playground 这类平台,但后端不训练自己的模型,而是对接第三方图像生成模型服务。
|
||||||
|
|
||||||
|
第一版要做的不是“一个展示页”,而是一套最小可用的产品闭环:
|
||||||
|
|
||||||
|
- 官网落地页
|
||||||
|
- 用户注册登录
|
||||||
|
- Prompt 输入与图片生成
|
||||||
|
- 图片历史记录与结果管理
|
||||||
|
- 套餐/额度体系
|
||||||
|
- 积分体系
|
||||||
|
- 图片分享与公开展示
|
||||||
|
- 点赞、评论、转发等互动能力
|
||||||
|
- 管理后台
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个面向普通创作者和独立开发者的现代 AI 生图 SaaS 平台,前端提供官网、生成工作台和分享社区,后端对接第三方生图模型,支持注册登录、按套餐购买积分、图片分享与互动。
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 用户工作台:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.1 技术选型建议
|
||||||
|
|
||||||
|
当前默认技术方案:
|
||||||
|
|
||||||
|
- 前端框架:`Next.js App Router`
|
||||||
|
- 用户鉴权:`Supabase Auth`
|
||||||
|
- 数据库:`Supabase Postgres`
|
||||||
|
- 文件存储:`Supabase Storage`
|
||||||
|
- 支付:`Stripe`
|
||||||
|
- 图像生成模型:通过统一后端适配层对接第三方模型 API
|
||||||
|
|
||||||
|
默认原因:
|
||||||
|
|
||||||
|
- `Supabase Auth + Supabase Postgres` 适合第一版 SaaS 快速落地
|
||||||
|
- 用户系统、数据库、对象存储可以一起解决
|
||||||
|
- 对 `app.xxx.com` 和 `admin.xxx.com` 两套前端都友好
|
||||||
|
- 后续如果要拆独立服务,也保留扩展空间
|
||||||
|
|
||||||
|
默认鉴权设计:
|
||||||
|
|
||||||
|
- 普通用户支持邮箱密码登录和第三方登录
|
||||||
|
- 管理员使用同一套登录系统,但在用户表中标记 `role=admin`
|
||||||
|
- 后台管理台必须校验管理员权限
|
||||||
|
- 用户前台与后台管理台接口分开鉴权
|
||||||
|
|
||||||
|
默认数据库设计:
|
||||||
|
|
||||||
|
- 主业务库使用 `PostgreSQL`
|
||||||
|
- 用户、任务、支付、积分、社区内容、监控日志先放一套主库
|
||||||
|
- 分析型查询先基于主库聚合,后续如数据量变大再拆分析库
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
WWW["www.xxx.com<br/>官网前台"] --> API["应用 API / 管理 API"]
|
||||||
|
APP["app.xxx.com<br/>用户工作台"] --> API
|
||||||
|
ADMIN["admin.xxx.com<br/>后台管理台"] --> API
|
||||||
|
API --> AUTH["Supabase Auth"]
|
||||||
|
API --> DB["Supabase Postgres"]
|
||||||
|
API --> OSS["OSS 对象存储"]
|
||||||
|
API --> PAY["Stripe"]
|
||||||
|
API --> MODEL["第三方生图模型"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 想快速生成营销图、封面图、海报图的普通用户
|
||||||
|
- 需要批量试 Prompt 的设计师或内容创作者
|
||||||
|
- 喜欢浏览他人作品并进行互动的社区用户
|
||||||
|
- 管理用户、任务和额度消耗的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 用户可以在 3 分钟内完成注册并生成第一张图
|
||||||
|
- 用户能清晰看到每次生成结果、积分消耗和历史记录
|
||||||
|
- 用户可以把满意作品分享出来并获得互动反馈
|
||||||
|
- 平台能支持积分购买、积分消耗、失败重试、内容互动和后台管理
|
||||||
|
|
||||||
|
建议北极星指标:
|
||||||
|
|
||||||
|
- 新用户首图生成成功率
|
||||||
|
- 日活跃生成用户数
|
||||||
|
- 人均生成次数
|
||||||
|
- 生成任务成功率
|
||||||
|
- 付费转化率
|
||||||
|
- 分享图片数
|
||||||
|
- 点赞/评论互动率
|
||||||
|
- 日活跃积分用户数
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 官网首页
|
||||||
|
- 注册/登录
|
||||||
|
- 生图工作台
|
||||||
|
- 图片历史页
|
||||||
|
- 套餐/积分页
|
||||||
|
- 积分页
|
||||||
|
- 支付/订阅能力
|
||||||
|
- 图片公开分享页
|
||||||
|
- 点赞、评论、转发
|
||||||
|
- 图片生成接口
|
||||||
|
- 生成任务状态查询
|
||||||
|
- 后台查看用户、生成任务、积分使用和内容互动情况
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 自训练模型
|
||||||
|
- 多模型工作流编排
|
||||||
|
- 图片编辑器
|
||||||
|
- 团队协作
|
||||||
|
- 多语言
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 游客 | 浏览官网、查看产品介绍、注册登录 |
|
||||||
|
| 注册用户 | 创建生成任务、查看历史图片、管理自己的积分和结果、查看积分明细、分享作品、点赞评论转发 |
|
||||||
|
| 管理员 | 查看用户、任务状态、失败日志、套餐与积分消耗情况,管理积分规则、公开内容与互动数据 |
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Next.js App Router
|
||||||
|
- TypeScript
|
||||||
|
- Tailwind CSS
|
||||||
|
- shadcn/ui
|
||||||
|
|
||||||
|
前端形态说明:
|
||||||
|
|
||||||
|
- 官网前台和用户工作台都属于“前端产品”
|
||||||
|
- 后台管理系统本质上也是前端页面,只是面向内部运营和管理员使用
|
||||||
|
- 因此本项目会有两套前端界面:
|
||||||
|
- 面向用户的产品前台
|
||||||
|
- 面向运营/管理员的后台管理台
|
||||||
|
- 同时后台管理台需要配套独立的管理员接口与权限校验
|
||||||
|
|
||||||
|
入口建议:
|
||||||
|
|
||||||
|
| 站点类型 | 建议入口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 官网前台 | `www.xxx.com` | 产品介绍、定价、FAQ、注册入口 |
|
||||||
|
| 用户工作台 | `app.xxx.com` | 登录后生成图片、看图库、看积分、发动态 |
|
||||||
|
| 后台管理台 | `admin.xxx.com` | 管理用户、套餐、任务、内容、风控 |
|
||||||
|
|
||||||
|
## 5.1 页面架构总览
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,19 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 用户工作台 `9` 个大页面
|
||||||
|
- 后台管理台 `9` 个大页面
|
||||||
|
|
||||||
|
### A. 官网前台 `www.xxx.com`
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- Hero 区与主 CTA
|
||||||
|
- 产品能力介绍
|
||||||
|
- 作品展示
|
||||||
|
- 套餐预览
|
||||||
|
- FAQ
|
||||||
|
- 注册/登录/进入工作台入口
|
||||||
|
|
||||||
|
### B. 用户工作台 `app.xxx.com`
|
||||||
|
|
||||||
|
#### 2. 登录页 `app:/login`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 邮箱/密码登录
|
||||||
|
- 第三方登录入口
|
||||||
|
- 找回密码入口
|
||||||
|
- 跳转注册页
|
||||||
|
|
||||||
|
#### 3. 注册页 `app:/register`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 新用户注册
|
||||||
|
- 同意协议与隐私政策
|
||||||
|
- 第三方登录注册
|
||||||
|
- 注册成功后进入工作台
|
||||||
|
|
||||||
|
#### 4. 生成工作台 `app:/generate`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 输入 Prompt 与 Negative Prompt
|
||||||
|
- 选择模型、比例、数量、质量参数
|
||||||
|
- 提交生图任务
|
||||||
|
- 查看生成中/成功/失败状态
|
||||||
|
- 对结果进行再次生成、收藏、发布
|
||||||
|
|
||||||
|
#### 5. 历史图库 `app:/gallery`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看个人历史生成记录
|
||||||
|
- 按时间/模型/状态筛选
|
||||||
|
- 删除图片
|
||||||
|
- 收藏图片
|
||||||
|
- 从历史记录再次进入详情或复用 Prompt
|
||||||
|
|
||||||
|
#### 6. 套餐页 `app:/billing`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看 Basic / Standard / Pro / Mega 套餐
|
||||||
|
- 月付/年付切换
|
||||||
|
- 查看每档套餐包含的积分和权益
|
||||||
|
- 发起购买套餐
|
||||||
|
- 购买额外积分包
|
||||||
|
- FAQ 与账号关联说明
|
||||||
|
|
||||||
|
#### 7. 积分页 `app:/points`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看当前积分余额
|
||||||
|
- 查看积分获取记录
|
||||||
|
- 查看积分消耗记录
|
||||||
|
- 每日签到
|
||||||
|
- 积分兑换权益或生成次数
|
||||||
|
|
||||||
|
#### 8. 社区广场 `app:/explore`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 浏览公开作品流
|
||||||
|
- 按热门/最新排序
|
||||||
|
- 点赞作品
|
||||||
|
- 评论作品
|
||||||
|
- 转发作品
|
||||||
|
- 进入作品详情页
|
||||||
|
|
||||||
|
#### 9. 作品详情页 `app:/posts/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看单个作品大图
|
||||||
|
- 查看作者信息与发布时间
|
||||||
|
- 查看完整 Prompt 与参数
|
||||||
|
- 查看点赞、评论、转发数据
|
||||||
|
- 复制 Prompt / 再次生成 / 点赞 / 评论 / 转发
|
||||||
|
|
||||||
|
#### 10. 个人中心 `app:/settings`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看个人资料
|
||||||
|
- 绑定/关联账号
|
||||||
|
- 查看当前套餐
|
||||||
|
- 查看登录方式与安全设置
|
||||||
|
- 管理公开分享偏好
|
||||||
|
|
||||||
|
### C. 后台管理台 `admin.xxx.com`
|
||||||
|
|
||||||
|
#### 11. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 用户总数
|
||||||
|
- 生成任务总量
|
||||||
|
- 支付收入概览
|
||||||
|
- 内容分享与互动概览
|
||||||
|
- 异常任务提醒
|
||||||
|
|
||||||
|
#### 12. 用户管理 `admin:/users`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看用户列表
|
||||||
|
- 搜索和筛选用户
|
||||||
|
- 查看用户套餐、积分、活跃情况
|
||||||
|
- 封禁/解封账号
|
||||||
|
- 手动调整积分
|
||||||
|
|
||||||
|
#### 13. 任务管理 `admin:/tasks`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看全部生成任务
|
||||||
|
- 按状态筛选成功/失败/处理中任务
|
||||||
|
- 查看失败原因
|
||||||
|
- 手动重试或标记异常任务
|
||||||
|
|
||||||
|
#### 14. 内容管理 `admin:/posts`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看公开作品列表
|
||||||
|
- 审核作品是否可展示
|
||||||
|
- 下架违规内容
|
||||||
|
- 查看评论与互动记录
|
||||||
|
- 审核或删除评论
|
||||||
|
|
||||||
|
#### 15. 套餐管理 `admin:/plans`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 配置套餐价格
|
||||||
|
- 配置月付/年付优惠
|
||||||
|
- 配置套餐积分数
|
||||||
|
- 配置积分包 top-up
|
||||||
|
- 配置并发和高级权益
|
||||||
|
|
||||||
|
#### 16. 支付订单 `admin:/billing`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看支付订单列表
|
||||||
|
- 查看订阅状态
|
||||||
|
- 查看退款/失败订单
|
||||||
|
- 搜索异常支付记录
|
||||||
|
|
||||||
|
#### 17. 运营配置 `admin:/operations`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 配置签到积分规则
|
||||||
|
- 配置分享/互动奖励规则
|
||||||
|
- 配置活动公告
|
||||||
|
- 配置风控和审核开关
|
||||||
|
|
||||||
|
#### 18. SaaS 指标看板 `admin:/analytics`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看新增用户、DAU、WAU、MAU
|
||||||
|
- 查看注册转化率、付费转化率
|
||||||
|
- 查看次日/7日/30日留存
|
||||||
|
- 查看套餐分布和订阅续费情况
|
||||||
|
- 查看积分发放、积分消耗、积分结余情况
|
||||||
|
- 查看社区分享数、点赞率、评论率、转发率
|
||||||
|
|
||||||
|
#### 19. 系统监控页 `admin:/observability`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看 API 调用量、成功率、错误率、平均耗时
|
||||||
|
- 查看第三方生图模型调用情况
|
||||||
|
- 查看数据库连接状态、慢查询和失败率
|
||||||
|
- 查看支付接口回调状态
|
||||||
|
- 查看任务队列积压和重试情况
|
||||||
|
- 查看系统告警与异常日志
|
||||||
|
|
||||||
|
建议页面明细:
|
||||||
|
|
||||||
|
| 页面 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 官网首页 | `www:/` | Hero、作品展示、功能介绍、价格方案、FAQ、CTA |
|
||||||
|
| 登录页 | `app:/login` | 登录表单 |
|
||||||
|
| 注册页 | `app:/register` | 注册表单 |
|
||||||
|
| 生成工作台 | `app:/generate` | Prompt、参数设置、任务提交、结果查看 |
|
||||||
|
| 历史图库 | `app:/gallery` | 查看历史图片、筛选、删除、收藏 |
|
||||||
|
| 套餐页 | `app:/billing` | 展示套餐档位、月付/年付、积分权益 |
|
||||||
|
| 积分页 | `app:/points` | 查看积分余额、获取记录、兑换规则 |
|
||||||
|
| 社区广场 | `app:/explore` | 浏览公开作品、点赞、评论、转发 |
|
||||||
|
| 作品详情页 | `app:/posts/:id` | 查看单张公开作品的详情与互动信息 |
|
||||||
|
| 个人中心 | `app:/settings` | 用户资料、积分、绑定信息 |
|
||||||
|
| 后台首页 | `admin:/` | 后台概览看板 |
|
||||||
|
| 用户管理 | `admin:/users` | 查看用户、封禁、积分与套餐状态 |
|
||||||
|
| 任务管理 | `admin:/tasks` | 查看生图任务、失败任务、重试情况 |
|
||||||
|
| 内容管理 | `admin:/posts` | 审核公开作品、评论、转发数据 |
|
||||||
|
| 套餐管理 | `admin:/plans` | 配置套餐、积分包、价格与权益 |
|
||||||
|
| 支付订单 | `admin:/billing` | 查看支付记录、退款状态、异常订单 |
|
||||||
|
| 运营配置 | `admin:/operations` | 配置签到规则、积分规则、公告与活动 |
|
||||||
|
| SaaS 指标看板 | `admin:/analytics` | 查看留存、转化、积分、订阅与社区活跃指标 |
|
||||||
|
| 系统监控页 | `admin:/observability` | 查看 API、模型调用、数据库、支付、队列状态 |
|
||||||
|
|
||||||
|
前端核心组件:
|
||||||
|
|
||||||
|
- Hero 区与 CTA
|
||||||
|
- Prompt 输入面板
|
||||||
|
- 模型参数配置区
|
||||||
|
- 图片结果卡片
|
||||||
|
- 任务状态轮询组件
|
||||||
|
- 图库列表/瀑布流
|
||||||
|
- 套餐卡片组件
|
||||||
|
- 月付/年付切换组件
|
||||||
|
- 积分概览卡片
|
||||||
|
- 积分明细列表
|
||||||
|
- FAQ 折叠区
|
||||||
|
- 公开作品卡片
|
||||||
|
- 评论列表与评论输入框
|
||||||
|
- 点赞/转发操作栏
|
||||||
|
- 套餐价格卡片
|
||||||
|
- 空态、加载、失败重试组件
|
||||||
|
- 管理后台表格、筛选器、统计卡片、审核面板
|
||||||
|
- 监控图表、趋势图、健康状态卡片、告警列表
|
||||||
|
|
||||||
|
前端状态与数据流:
|
||||||
|
|
||||||
|
- 游客从首页进入注册或登录
|
||||||
|
- 登录后进入 `/generate`
|
||||||
|
- 用户输入 Prompt 和参数后提交生成任务
|
||||||
|
- 前端轮询或订阅任务状态
|
||||||
|
- 成功后展示图片并写入历史记录
|
||||||
|
- 用户完成签到、生成、分享、互动后可获得积分
|
||||||
|
- 用户可将图片发布到公开广场
|
||||||
|
- 其他用户可点赞、评论、转发该作品
|
||||||
|
- 套餐页展示剩余积分、套餐差异与升级入口
|
||||||
|
- 积分页展示积分来源、消费记录和兑换入口
|
||||||
|
- 管理员从独立后台入口进入运营看板和管理模块
|
||||||
|
- 管理员可在后台查看业务指标和系统健康状态
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Next.js Route Handlers 或 Node.js/Express
|
||||||
|
- PostgreSQL / Supabase
|
||||||
|
- 对接第三方图像生成模型 API
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `auth`:注册、登录、鉴权
|
||||||
|
- `generation`:创建生图任务、查询任务状态、失败重试
|
||||||
|
- `images`:图片历史、删除、收藏、详情
|
||||||
|
- `points`:积分购买、累计、扣减、任务奖励、兑换记录
|
||||||
|
- `billing`:套餐、支付记录、升级状态
|
||||||
|
- `social`:公开发布、点赞、评论、转发
|
||||||
|
- `analytics`:留存、转化、订阅、积分、社区活跃统计
|
||||||
|
- `observability`:API 调用、模型调用、数据库状态、告警日志
|
||||||
|
- `admin`:后台查看用户、任务、错误日志、审核内容、运营配置
|
||||||
|
|
||||||
|
核心数据流:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
user["用户"] --> gen["提交生成任务"]
|
||||||
|
gen --> payCheck["检查套餐/积分"]
|
||||||
|
payCheck --> model["调用第三方生图模型"]
|
||||||
|
model --> oss["上传结果到 OSS"]
|
||||||
|
oss --> db["写入 Postgres: tasks / images / points"]
|
||||||
|
db --> gallery["历史图库 / 社区发布"]
|
||||||
|
gallery --> social["点赞 / 评论 / 转发"]
|
||||||
|
social --> db
|
||||||
|
db --> analytics["SaaS 指标看板"]
|
||||||
|
db --> observability["API / DB / Provider 监控"]
|
||||||
|
```
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
profiles (
|
||||||
|
id uuid primary key,
|
||||||
|
email text,
|
||||||
|
role text,
|
||||||
|
plan text,
|
||||||
|
points int,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
generation_tasks (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
prompt text,
|
||||||
|
negative_prompt text,
|
||||||
|
model text,
|
||||||
|
aspect_ratio text,
|
||||||
|
image_count int,
|
||||||
|
status text,
|
||||||
|
error_message text,
|
||||||
|
provider_task_id text,
|
||||||
|
points_cost int,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
generated_images (
|
||||||
|
id uuid primary key,
|
||||||
|
task_id uuid,
|
||||||
|
user_id uuid,
|
||||||
|
image_url text,
|
||||||
|
width int,
|
||||||
|
height int,
|
||||||
|
is_favorite boolean,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
billing_records (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
plan_code text,
|
||||||
|
billing_cycle text,
|
||||||
|
type text,
|
||||||
|
amount_cents int,
|
||||||
|
points_delta int,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
point_records (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
type text,
|
||||||
|
points_delta int,
|
||||||
|
source text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
api_call_logs (
|
||||||
|
id uuid primary key,
|
||||||
|
route text,
|
||||||
|
method text,
|
||||||
|
user_id uuid,
|
||||||
|
status_code int,
|
||||||
|
duration_ms int,
|
||||||
|
request_id text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
provider_call_logs (
|
||||||
|
id uuid primary key,
|
||||||
|
provider_name text,
|
||||||
|
task_id uuid,
|
||||||
|
status text,
|
||||||
|
duration_ms int,
|
||||||
|
error_message text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
system_health_checks (
|
||||||
|
id uuid primary key,
|
||||||
|
service_name text,
|
||||||
|
check_type text,
|
||||||
|
status text,
|
||||||
|
detail jsonb,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
subscription_plans (
|
||||||
|
id uuid primary key,
|
||||||
|
code text,
|
||||||
|
name text,
|
||||||
|
monthly_price_cents int,
|
||||||
|
yearly_price_cents int,
|
||||||
|
monthly_points int,
|
||||||
|
concurrent_image_jobs int,
|
||||||
|
concurrent_video_jobs int,
|
||||||
|
supports_hd_video boolean,
|
||||||
|
supports_stealth boolean,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
shared_posts (
|
||||||
|
id uuid primary key,
|
||||||
|
image_id uuid,
|
||||||
|
user_id uuid,
|
||||||
|
caption text,
|
||||||
|
visibility text,
|
||||||
|
repost_from_post_id uuid,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
post_likes (
|
||||||
|
id uuid primary key,
|
||||||
|
post_id uuid,
|
||||||
|
user_id uuid,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
post_comments (
|
||||||
|
id uuid primary key,
|
||||||
|
post_id uuid,
|
||||||
|
user_id uuid,
|
||||||
|
content text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 功能清单
|
||||||
|
|
||||||
|
必须完成:
|
||||||
|
|
||||||
|
- 官网价值展示
|
||||||
|
- 注册/登录
|
||||||
|
- Prompt 输入与参数选择
|
||||||
|
- 图片生成任务提交
|
||||||
|
- 图片结果展示
|
||||||
|
- 历史记录查看
|
||||||
|
- 套餐/积分展示
|
||||||
|
- 积分展示与明细
|
||||||
|
- 支付/订阅
|
||||||
|
- 图片公开分享
|
||||||
|
- 点赞、评论、转发
|
||||||
|
- 后台独立入口
|
||||||
|
- 管理员查看任务、用户、支付和社区内容
|
||||||
|
- 管理员审核公开内容与评论
|
||||||
|
- 管理员配置积分规则与套餐规则
|
||||||
|
- 后台查看 SaaS 留存、转化、积分与订阅指标
|
||||||
|
- 后台查看 API 调用、模型调用和数据库健康状态
|
||||||
|
|
||||||
|
可选增强:
|
||||||
|
|
||||||
|
- 图片收藏
|
||||||
|
- 再次生成同款
|
||||||
|
- Prompt 模板
|
||||||
|
- 水印与下载规格选择
|
||||||
|
- 任务失败自动重试
|
||||||
|
- 评论通知
|
||||||
|
- 个人主页与作品墙
|
||||||
|
- 积分兑换生成次数或高级功能
|
||||||
|
|
||||||
|
## 8.1 套餐设计草案
|
||||||
|
|
||||||
|
套餐逻辑:
|
||||||
|
|
||||||
|
- 用户购买的是 `积分型订阅套餐`
|
||||||
|
- 月付和年付两种计费方式
|
||||||
|
- 年付默认比月付优惠 `20%`
|
||||||
|
- 套餐按月发放积分
|
||||||
|
- 生成图片、生成视频、高清能力、并发能力由套餐共同决定
|
||||||
|
|
||||||
|
建议档位:
|
||||||
|
|
||||||
|
| 套餐 | 月付 | 年付折后 | 每月积分 | 图片并发 | 视频并发 | 其他权益 |
|
||||||
|
|------|------|------|------|------|------|------|
|
||||||
|
| Basic | `$10` | `$8` | 2000 | 3 | 1 | 基础生图、可补充购买积分 |
|
||||||
|
| Standard | `$30` | `$24` | 8000 | 3 | 3 | 支持高清视频、无限慢速图像生成 |
|
||||||
|
| Pro | `$60` | `$48` | 18000 | 12 | 6 | 隐身生成、更多并发 |
|
||||||
|
| Mega | `$120` | `$96` | 40000 | 12 | 12 | 更高上限、适合高频创作用户 |
|
||||||
|
|
||||||
|
补充说明:
|
||||||
|
|
||||||
|
- 套餐价格和积分数值是第一版草案,后续可调整
|
||||||
|
- 不同模型与分辨率对应不同积分消耗
|
||||||
|
- 视频生成会比图片生成消耗更多积分
|
||||||
|
- 支持额外购买积分包作为 top-up
|
||||||
|
|
||||||
|
建议 FAQ 内容:
|
||||||
|
|
||||||
|
- 我买了套餐但没生效怎么办?
|
||||||
|
- 月付和年付有什么差别?
|
||||||
|
- 积分用完了怎么办?
|
||||||
|
- 积分会不会过期?
|
||||||
|
- 账号能不能绑定多个登录方式?
|
||||||
|
- 哪些内容支持公开分享?
|
||||||
|
|
||||||
|
## 9. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/auth/register` | 用户注册 |
|
||||||
|
| `POST` | `/api/auth/login` | 用户登录 |
|
||||||
|
| `POST` | `/api/auth/link-account` | 关联不同登录账号 |
|
||||||
|
| `GET` | `/api/me` | 获取当前用户资料与积分 |
|
||||||
|
| `GET` | `/api/points` | 获取积分余额和明细 |
|
||||||
|
| `POST` | `/api/points/check-in` | 每日签到获取积分 |
|
||||||
|
| `POST` | `/api/points/redeem` | 积分兑换权益或生成次数 |
|
||||||
|
| `POST` | `/api/generations` | 创建生图任务 |
|
||||||
|
| `GET` | `/api/generations/:id` | 获取任务状态和结果 |
|
||||||
|
| `GET` | `/api/gallery` | 获取当前用户历史图片 |
|
||||||
|
| `DELETE` | `/api/gallery/:id` | 删除某张图片 |
|
||||||
|
| `PATCH` | `/api/gallery/:id/favorite` | 收藏/取消收藏图片 |
|
||||||
|
| `GET` | `/api/billing/plans` | 获取套餐列表 |
|
||||||
|
| `POST` | `/api/billing/checkout` | 创建支付订单或订阅会话 |
|
||||||
|
| `POST` | `/api/billing/top-up` | 购买额外积分包 |
|
||||||
|
| `GET` | `/api/billing/records` | 获取消费与充值记录 |
|
||||||
|
| `POST` | `/api/posts` | 将一张图片发布为公开作品 |
|
||||||
|
| `GET` | `/api/posts` | 获取公开作品流 |
|
||||||
|
| `GET` | `/api/posts/:id` | 获取作品详情 |
|
||||||
|
| `POST` | `/api/posts/:id/likes` | 点赞作品 |
|
||||||
|
| `DELETE` | `/api/posts/:id/likes` | 取消点赞 |
|
||||||
|
| `POST` | `/api/posts/:id/comments` | 评论作品 |
|
||||||
|
| `POST` | `/api/posts/:id/repost` | 转发作品 |
|
||||||
|
| `GET` | `/api/admin/overview` | 获取后台总览 |
|
||||||
|
| `GET` | `/api/admin/users` | 获取用户列表与账户状态 |
|
||||||
|
| `GET` | `/api/admin/tasks` | 获取生成任务列表 |
|
||||||
|
| `GET` | `/api/admin/posts` | 获取公开作品与互动列表 |
|
||||||
|
| `GET` | `/api/admin/analytics/overview` | 获取新增、活跃、付费转化等核心 SaaS 指标 |
|
||||||
|
| `GET` | `/api/admin/analytics/retention` | 获取次日/7日/30日留存数据 |
|
||||||
|
| `GET` | `/api/admin/analytics/points` | 获取积分发放、消耗、结余数据 |
|
||||||
|
| `GET` | `/api/admin/analytics/subscriptions` | 获取订阅与套餐分布数据 |
|
||||||
|
| `PATCH` | `/api/admin/posts/:id/moderate` | 审核或下架公开作品 |
|
||||||
|
| `PATCH` | `/api/admin/comments/:id/moderate` | 审核或删除评论 |
|
||||||
|
| `GET` | `/api/admin/billing` | 获取支付订单与订阅记录 |
|
||||||
|
| `GET` | `/api/admin/plans` | 获取套餐与积分包配置 |
|
||||||
|
| `PATCH` | `/api/admin/plans/:id` | 更新套餐配置 |
|
||||||
|
| `GET` | `/api/admin/point-rules` | 获取积分规则 |
|
||||||
|
| `PATCH` | `/api/admin/point-rules` | 更新积分规则 |
|
||||||
|
| `GET` | `/api/admin/observability/apis` | 获取 API 调用量、错误率、耗时等监控数据 |
|
||||||
|
| `GET` | `/api/admin/observability/providers` | 获取第三方模型调用情况 |
|
||||||
|
| `GET` | `/api/admin/observability/database` | 获取数据库连接、慢查询、失败率 |
|
||||||
|
| `GET` | `/api/admin/observability/health` | 获取系统健康检查结果 |
|
||||||
|
|
||||||
|
`POST /api/generations` 请求示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"prompt": "a cinematic futuristic city at sunset, ultra detailed",
|
||||||
|
"negativePrompt": "blurry, low quality",
|
||||||
|
"model": "flux-dev",
|
||||||
|
"aspectRatio": "1:1",
|
||||||
|
"imageCount": 4
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. 非功能要求
|
||||||
|
|
||||||
|
- 生成过程有明确状态反馈
|
||||||
|
- 失败任务能提示原因
|
||||||
|
- 移动端至少可查看和浏览历史结果
|
||||||
|
- 首页具备现代 SaaS 视觉质量
|
||||||
|
- 用户只能访问自己的图片和任务
|
||||||
|
- 积分扣减逻辑要稳定可追踪
|
||||||
|
- 积分发放与扣减逻辑要可审计
|
||||||
|
- 公开内容需要有最小审核或风控预留能力
|
||||||
|
- 互动接口需要防刷和限流预留
|
||||||
|
- 管理后台关键指标需支持日/周/月维度查看
|
||||||
|
- API 日志、数据库状态、第三方模型调用结果需可追踪
|
||||||
|
|
||||||
|
## 11. 开发顺序建议
|
||||||
|
|
||||||
|
1. 搭官网首页与登录注册页
|
||||||
|
2. 实现用户鉴权
|
||||||
|
3. 实现生成工作台 UI
|
||||||
|
4. 接入生图任务接口
|
||||||
|
5. 实现历史图库
|
||||||
|
6. 实现支付、套餐、积分与 FAQ 页
|
||||||
|
7. 实现分享、点赞、评论、转发
|
||||||
|
8. 实现独立后台入口与后台任务、用户、积分、支付、内容管理页
|
||||||
|
9. 实现 SaaS 指标看板与系统监控页
|
||||||
|
|
||||||
|
## 12. 待确认项
|
||||||
|
|
||||||
|
- 第三方模型服务优先接哪一家
|
||||||
|
- 图片是否允许公开分享
|
||||||
|
- 后台是否必须使用独立二级域名,还是允许先用独立路由入口
|
||||||
|
- 积分获取规则是签到 + 分享 + 互动,还是还要包含邀请奖励
|
||||||
|
- 积分是否只用于生成消耗,还是还要兑换会员权益
|
||||||
|
- 年付优惠是否固定为 `20%`
|
||||||
|
- 是否需要单独的积分包 top-up
|
||||||
|
- 鉴权是否接受默认方案:`Supabase Auth`
|
||||||
|
- 数据库是否接受默认方案:`Supabase Postgres`
|
||||||
|
- 留存与系统监控是否先做基础后台报表,后续再接专业监控平台
|
||||||
|
- 评论是否允许二级回复
|
||||||
|
- 转发是站内转发,还是还要带外链分享
|
||||||
|
- 第一版是否需要人工审核公开作品
|
||||||
@@ -1,228 +1,174 @@
|
|||||||
# 现代网页落地页
|
# 现代 AI 生图 SaaS 开发实战
|
||||||
|
|
||||||
很多同学会写功能页,但一到“让用户第一次看到就愿意注册”的落地页就卡住了。
|
这个项目不再只是“做一个页面”,而是围绕一份真实 PRD,把一个 AI 生图 SaaS 从想法推进到可上线产品。
|
||||||
|
|
||||||
这份大作业就是专门练这件事:你要做一个真正能承接流量、讲清价值、引导转化的现代落地页,而不是“看起来像作业”的静态展示页。
|
你会同时看到三件事:
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
- 项目要做成什么
|
||||||
打造一个 **可上线的现代产品落地页**。页面需要包含价值主张、核心功能展示、用户证言、价格方案、FAQ、明确 CTA(注册/预约演示)以及基础数据埋点,最终可以用于真实投放或作品集展示。
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
|
::: tip PRD 入口
|
||||||
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定定位', description: '先锁定目标用户、价值主张与转化目标' },
|
{ title: '看 PRD', description: '先明确页面、功能、鉴权、数据库、支付与监控范围' },
|
||||||
{ title: '搭结构', description: '搭出页面区块、导航和响应式骨架' },
|
{ title: '生成骨架', description: '让 AI 先产出前台、工作台、后台三套界面骨架' },
|
||||||
{ title: '做转化', description: '补齐文案、视觉、CTA 与埋点' },
|
{ title: '监工迭代', description: '逐页验收、补接口、修权限、补监控与数据链路' },
|
||||||
{ title: '上线交付', description: '性能优化、部署与演示材料整理' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的 SaaS 原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个题目值得做?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
因为落地页不是“前端练习题”,而是产品和增长的交叉点。
|
这是一个参考 Midjourney 产品体验的现代 AI 生图 SaaS:
|
||||||
|
|
||||||
- 你会练到结构化表达:30 秒内让用户知道你是谁、你解决什么问题
|
- 官网前台:负责产品介绍、定价、FAQ、注册转化
|
||||||
- 你会练到工程能力:组件化、响应式、性能优化、SEO 基础
|
- 用户工作台:负责 Prompt 输入、图片生成、图库、积分、套餐、社区互动
|
||||||
- 你会练到转化意识:CTA 设计、表单路径、埋点事件、A/B 迭代
|
- 后台管理台:负责用户、任务、支付、积分、内容审核、SaaS 指标和系统监控
|
||||||
|
|
||||||
做完这个项目,你不仅能做“页面”,还能做“会转化的页面”。
|
同时,后端需要接住这些关键能力:
|
||||||
|
|
||||||
## 先看全景:一张图看懂这个作业
|
- 用户鉴权
|
||||||
|
- 图片生成任务
|
||||||
|
- OSS 对象存储
|
||||||
|
- 积分与套餐支付
|
||||||
|
- 图片分享、点赞、评论、转发
|
||||||
|
- 留存、转化、API 调用、数据库状态监控
|
||||||
|
|
||||||
|
## 开发过程怎么走?
|
||||||
|
|
||||||
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
|
先把这几个问题看清楚:
|
||||||
|
|
||||||
|
- 有几个入口:`www / app / admin`
|
||||||
|
- 有几个大页面
|
||||||
|
- 每个页面的核心功能是什么
|
||||||
|
- 后端模块和数据库表有哪些
|
||||||
|
- 第一版哪些做,哪些不做
|
||||||
|
|
||||||
|
如果 PRD 没拍板,就不要开始开发。
|
||||||
|
|
||||||
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
|
第一轮不是要它一次性写完,而是先生成:
|
||||||
|
|
||||||
|
- 官网首页
|
||||||
|
- 登录注册
|
||||||
|
- 生图工作台
|
||||||
|
- 历史图库
|
||||||
|
- 套餐/积分页
|
||||||
|
- 社区广场
|
||||||
|
- 后台首页与管理页骨架
|
||||||
|
|
||||||
|
这一步的目标是:把信息架构、路由、页面分工先搭出来。
|
||||||
|
|
||||||
|
### 3. 再进入“监工模式”
|
||||||
|
|
||||||
|
真正难的不是生成第一版,而是持续监工。
|
||||||
|
|
||||||
|
你要盯的重点包括:
|
||||||
|
|
||||||
|
- 页面结构是不是和 PRD 一致
|
||||||
|
- 前台、工作台、后台入口有没有分清
|
||||||
|
- 鉴权是不是做对了
|
||||||
|
- 普通用户和管理员权限有没有串
|
||||||
|
- 积分、支付、生成任务的状态流是不是闭环
|
||||||
|
- OSS 上传、数据库写入、任务状态更新是不是一致
|
||||||
|
- 后台有没有 SaaS 指标和系统监控
|
||||||
|
|
||||||
|
可以把 AI 当成执行者,但你自己要做“产品经理 + 技术负责人 + QA”。
|
||||||
|
|
||||||
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
|
最后一轮不是补页面,而是把完整链路跑通:
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
ad["流量来源: 社媒 / 搜索 / 社群"] --> landing["落地页首页"]
|
prd["PRD"] --> web["官网前台"]
|
||||||
landing --> value["价值主张区"]
|
prd --> app["用户工作台"]
|
||||||
landing --> features["功能展示区"]
|
prd --> admin["后台管理台"]
|
||||||
landing --> social["用户证言 / 案例"]
|
app --> auth["鉴权"]
|
||||||
landing --> pricing["价格与方案"]
|
app --> gen["图片生成任务"]
|
||||||
landing --> faq["常见问题"]
|
gen --> oss["OSS 对象存储"]
|
||||||
value --> cta["主 CTA: 立即注册 / 预约演示"]
|
gen --> db["数据库"]
|
||||||
pricing --> cta
|
billing["支付与套餐"] --> db
|
||||||
faq --> cta
|
social["分享 / 点赞 / 评论 / 转发"] --> db
|
||||||
cta --> form["注册/预约表单"]
|
admin --> analytics["SaaS 指标看板"]
|
||||||
form --> success["成功页 / 感谢页"]
|
admin --> observability["API / DB / Provider 监控"]
|
||||||
form --> event["埋点事件上报"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
这张图表达的核心是:你的目标不是把每个模块都写出来,而是让用户自然走到 CTA 并完成动作。
|
只要这条链路能跑通,这个项目就不是“Demo 页面”,而是一个完整产品原型。
|
||||||
|
|
||||||
## 1. 定定位:先把“做给谁看”讲清楚
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
### 建议你先写出这 4 句话
|
推荐按模块逐步下指令,而不是一句“帮我做完”。
|
||||||
|
|
||||||
1. 我们的产品是什么?
|
例如先让它生成三套前端骨架:
|
||||||
2. 目标用户是谁?
|
|
||||||
3. 用户最痛的一个问题是什么?
|
|
||||||
4. 用户看完页面后希望他做什么动作?
|
|
||||||
|
|
||||||
### 项目边界(MVP)
|
|
||||||
|
|
||||||
第一版请严格控制范围:
|
|
||||||
|
|
||||||
- 只做 **单页落地页**,不要先做完整后台
|
|
||||||
- CTA 先聚焦 **一个主动作**(注册或预约演示二选一)
|
|
||||||
- 只做 **一个核心受众**,不要同时覆盖所有人群
|
|
||||||
- 先做静态内容 + 基础交互,不做复杂动画大片
|
|
||||||
- 埋点只做关键 3~5 个事件,不做全链路数据平台
|
|
||||||
|
|
||||||
### 页面模块规划
|
|
||||||
|
|
||||||
| 模块 | 目标 | 最低要求 |
|
|
||||||
|------|------|------|
|
|
||||||
| Hero 区 | 5 秒内传达价值 | 标题、副标题、主 CTA、视觉主图 |
|
|
||||||
| 功能区 | 解释“怎么解决” | 3~6 个核心能力卡片 |
|
|
||||||
| 信任区 | 提升可信度 | 用户证言、Logo、案例之一 |
|
|
||||||
| 价格区 | 降低决策成本 | 至少两档方案,强调推荐方案 |
|
|
||||||
| FAQ | 处理犹豫 | 4~8 个高频问题 |
|
|
||||||
| Footer | 完整闭环 | 联系方式、隐私/条款入口 |
|
|
||||||
|
|
||||||
## 2. 搭结构:先做骨架,再做精修
|
|
||||||
|
|
||||||
### 推荐技术栈
|
|
||||||
|
|
||||||
- **Next.js App Router** 或 **Vite + React**
|
|
||||||
- **TypeScript**
|
|
||||||
- **Tailwind CSS**
|
|
||||||
- **shadcn/ui**(可选)
|
|
||||||
- **Vercel Analytics / 自定义埋点**
|
|
||||||
|
|
||||||
### 第一步:生成可运行的页面骨架
|
|
||||||
|
|
||||||
你可以先让 AI IDE 生成第一版结构:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我创建一个现代 SaaS 落地页(Next.js + TypeScript + Tailwind)。
|
请基于当前 PRD,帮我生成一个现代 AI 生图 SaaS 的前端骨架。
|
||||||
|
|
||||||
页面区块:
|
|
||||||
1. 顶部导航(logo、锚点、登录、注册)
|
|
||||||
2. Hero 区(主标题、副标题、CTA)
|
|
||||||
3. 功能介绍区(6 张卡片)
|
|
||||||
4. 用户证言区
|
|
||||||
5. 价格区(Free/Pro/Team)
|
|
||||||
6. FAQ 区(手风琴)
|
|
||||||
7. 页脚
|
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
- 风格现代、简洁,不要像课堂作业
|
1. 分成三个入口:www、app、admin
|
||||||
- 先实现响应式布局
|
2. 官网包括:首页、定价、FAQ
|
||||||
- 所有 CTA 有 hover/active 状态
|
3. app 包括:登录、注册、生成工作台、图库、套餐、积分、社区、作品详情、个人中心
|
||||||
- 预留事件埋点函数
|
4. admin 包括:后台首页、用户管理、任务管理、内容管理、套餐管理、支付订单、运营配置、SaaS 指标、系统监控
|
||||||
|
5. 先只生成页面结构和假数据,不接真实接口
|
||||||
|
6. 风格参考 Midjourney,简洁、现代、带产品感
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第二步:补齐文案与信息层级
|
然后再一块一块补:
|
||||||
|
|
||||||
很多页面做不出转化,根因是信息顺序错了。你可以继续给 AI IDE:
|
- 鉴权
|
||||||
|
- 数据库
|
||||||
|
- OSS 上传
|
||||||
|
- 支付
|
||||||
|
- 积分系统
|
||||||
|
- 社区互动
|
||||||
|
- 后台统计和监控
|
||||||
|
|
||||||
```text
|
## 怎么“监工”才有效?
|
||||||
请优化我的落地页文案结构,目标是提高注册转化率。
|
|
||||||
|
|
||||||
背景:
|
每做完一个模块,至少检查这 5 件事:
|
||||||
- 目标用户:独立开发者和小团队
|
|
||||||
- 核心价值:用 AI 自动生成营销内容
|
|
||||||
- 主转化动作:点击“免费开始”
|
|
||||||
|
|
||||||
请输出:
|
| 检查项 | 要看什么 |
|
||||||
1. Hero 标题 5 个备选
|
|------|------|
|
||||||
2. 副标题 5 个备选
|
| 页面是否对 | 页面数量、入口、功能是否符合 PRD |
|
||||||
3. CTA 按钮文案 5 个备选
|
| 接口是否对 | 请求参数、返回结构、状态处理是否合理 |
|
||||||
4. 每个功能卡片的一句话价值描述
|
| 权限是否对 | 普通用户和管理员是否隔离 |
|
||||||
5. FAQ 建议问题列表
|
| 数据是否对 | 数据库、OSS、支付、积分是否一致 |
|
||||||
```
|
| 演示是否对 | 是否真的能给别人完整演示一条链路 |
|
||||||
|
|
||||||
### 第三步:加关键交互与状态
|
如果发现 AI 写偏了,不要整页推翻,直接让它改具体模块。
|
||||||
|
|
||||||
至少补齐这几项:
|
## 最后的预期效果
|
||||||
|
|
||||||
- CTA 点击 loading 状态
|
做完后,你应该拿到这些交付物:
|
||||||
- 表单提交成功/失败反馈
|
|
||||||
- 页面锚点平滑滚动
|
|
||||||
- 移动端菜单展开/收起
|
|
||||||
- 表单字段基础校验
|
|
||||||
|
|
||||||
## 3. 做转化:从“好看”走向“有效”
|
- 一套可运行的 AI 生图 SaaS 项目
|
||||||
|
- 一份同级 PRD 文档
|
||||||
### 最小埋点方案
|
- 三套入口:`www / app / admin`
|
||||||
|
- 基础鉴权、支付、积分、OSS、社区互动、后台管理
|
||||||
建议先只做以下事件:
|
- SaaS 指标看板和系统监控页
|
||||||
|
- 一份 README
|
||||||
| 事件名 | 触发时机 | 目的 |
|
- 一个可以演示的线上版本或本地完整运行方案
|
||||||
|------|------|------|
|
|
||||||
| `view_hero` | 首屏展示 | 统计曝光 |
|
|
||||||
| `click_primary_cta` | 点击主 CTA | 统计主转化意图 |
|
|
||||||
| `view_pricing` | 价格区进入视口 | 评估价格区关注度 |
|
|
||||||
| `submit_lead_form` | 提交表单 | 统计核心转化 |
|
|
||||||
| `submit_lead_form_error` | 提交失败 | 发现转化阻塞点 |
|
|
||||||
|
|
||||||
### 转化路径时序图
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
actor User as 访客
|
|
||||||
participant Page as 落地页
|
|
||||||
participant Form as 注册表单
|
|
||||||
participant API as 提交接口
|
|
||||||
participant Analytics as 埋点系统
|
|
||||||
|
|
||||||
User->>Page: 打开页面
|
|
||||||
Page->>Analytics: view_hero
|
|
||||||
User->>Page: 点击主 CTA
|
|
||||||
Page->>Analytics: click_primary_cta
|
|
||||||
Page->>Form: 打开表单
|
|
||||||
User->>Form: 填写并提交
|
|
||||||
Form->>API: POST /api/leads
|
|
||||||
API-->>Form: success / error
|
|
||||||
Form->>Analytics: submit_lead_form 或 submit_lead_form_error
|
|
||||||
Form-->>User: 显示成功或失败反馈
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. 上线交付:从“能跑”到“能展示”
|
|
||||||
|
|
||||||
### 部署前检查
|
|
||||||
|
|
||||||
- Lighthouse 移动端性能建议 75+(第一版即可)
|
|
||||||
- 图片已压缩并使用现代格式
|
|
||||||
- 标题、描述、OG 基础信息已配置
|
|
||||||
- 所有 CTA 都有真实目标行为
|
|
||||||
- 关键事件埋点可在控制台看到
|
|
||||||
|
|
||||||
### 交付物
|
|
||||||
|
|
||||||
- 线上链接(Vercel/Netlify 等)
|
|
||||||
- 项目仓库地址
|
|
||||||
- 主要页面截图(桌面端 + 移动端)
|
|
||||||
- 60 秒演示视频(讲清目标用户与转化路径)
|
|
||||||
- README(启动方式、技术栈、埋点说明)
|
|
||||||
|
|
||||||
## 验收标准
|
## 验收标准
|
||||||
|
|
||||||
| 维度 | 最低达标 | 加分项 |
|
| 维度 | 最低达标 |
|
||||||
|------|------|------|
|
|------|------|
|
||||||
| 页面完整度 | Hero/功能/价格/FAQ/页脚完整 | 信息密度与视觉层级优秀 |
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
| 转化设计 | 有明确主 CTA 和提交流程 | CTA 文案与位置经过对比优化 |
|
| 产品闭环 | 注册、购买积分、生成图片、查看历史、分享互动可以跑通 |
|
||||||
| 工程质量 | 响应式正常、交互状态完整 | 组件拆分清晰、复用性高 |
|
| 后台能力 | 用户、任务、支付、内容、积分、监控可以查看 |
|
||||||
| 数据意识 | 关键事件埋点可用 | 有初步转化漏斗分析 |
|
| 工程完整度 | 前端、后端、数据库、OSS、支付链路都已接通 |
|
||||||
| 交付能力 | 可访问链接 + README + 演示视频 | Lighthouse、SEO、无障碍基础优化 |
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的完整过程 |
|
||||||
|
|
||||||
## 提交前最后检查
|
::: tip 🚀 做完这个项目,你会得到什么?
|
||||||
|
你得到的不只是一个页面,也不只是一个小功能,而是一套完整的 AI SaaS 产品开发过程样例。后面再做别的项目,你可以继续沿用这套“先 PRD、再生成、再监工、再联调上线”的方法。
|
||||||
<el-card shadow="hover" style="margin: 20px 0; border-radius: 12px;">
|
|
||||||
<template #header>
|
|
||||||
<div style="font-weight: bold; font-size: 16px;">提交前最后看一眼</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<ul style="list-style-type: none; padding-left: 0;">
|
|
||||||
<li><label><input type="checkbox" disabled /> 页面核心区块已全部完成并可访问</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 主 CTA 路径可真实触发提交动作</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 桌面端和移动端布局都可正常使用</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 至少 3 个关键埋点事件已验证</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 项目已部署并准备演示材料</label></li>
|
|
||||||
</ul>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
::: tip 🚀 完成后你会得到什么?
|
|
||||||
这会是你作品集中最“有商业味道”的页面之一。它证明你不只会做界面,还能围绕目标用户和转化结果来做产品页面。
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
@@ -0,0 +1,408 @@
|
|||||||
|
# PRD:Spring Boot 电影推荐系统
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:明确推荐系统项目的最小可用边界和前后端分工。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个“带推荐能力的电影站点”,不是纯展示页面。它需要把用户行为沉淀下来,并给出可解释推荐。
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个包含电影浏览、评分收藏、推荐结果与后台管理的电影推荐系统。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
WWW["www.xxx.com<br/>官网前台"] --> API["应用 API / 管理 API"]
|
||||||
|
APP["app.xxx.com<br/>用户前台"] --> API
|
||||||
|
ADMIN["admin.xxx.com<br/>后台管理台"] --> API
|
||||||
|
API --> AUTH["JWT Auth"]
|
||||||
|
API --> DB["MySQL"]
|
||||||
|
API --> REC["Recommendation Service"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.0 技术选型建议
|
||||||
|
|
||||||
|
- 前端框架:`React` 或 `Vue`
|
||||||
|
- 后端框架:`Spring Boot 3`
|
||||||
|
- 数据库:`MySQL`
|
||||||
|
- 鉴权:`JWT`
|
||||||
|
- 缓存:`Redis`(可选)
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 用户前台:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.1 竞品参考(官方)
|
||||||
|
|
||||||
|
- [Letterboxd](https://letterboxd.com/)
|
||||||
|
- [IMDb](https://www.imdb.com/)
|
||||||
|
|
||||||
|
## 1.2 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考真实电影产品的做法:
|
||||||
|
|
||||||
|
- 借鉴 `Letterboxd` 的社区化电影浏览体验:电影卡片、评分、收藏、个人记录要自然串起来
|
||||||
|
- 借鉴 `IMDb` 的详情页信息组织:海报、简介、标签、评分、演员和关联内容分层展示
|
||||||
|
- 推荐页不能只是一个列表,应当同时展示推荐理由
|
||||||
|
- 个人中心要强调“我的评分 / 我的收藏 / 我的推荐偏好”
|
||||||
|
- 后台管理应像内容后台,而不是简单 CRUD 页面
|
||||||
|
|
||||||
|
## 1.3 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `Letterboxd` 首页与个人页
|
||||||
|
- 重点看:电影浏览、评分记录、收藏和个人偏好的组织方式
|
||||||
|
- `IMDb` 电影详情页
|
||||||
|
- 重点看:海报、简介、标签、评分、演员与相关内容的层次
|
||||||
|
- `IMDb` 排行榜和推荐内容区域
|
||||||
|
- 重点看:卡片式展示和浏览路径设计
|
||||||
|
|
||||||
|
因此本项目建议:
|
||||||
|
|
||||||
|
- 列表页更像内容浏览页
|
||||||
|
- 详情页更像内容详情页
|
||||||
|
- 推荐页更像“为你推荐”
|
||||||
|
- 后台页更像内容运营后台
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 浏览和筛选电影的普通用户
|
||||||
|
- 愿意通过评分与收藏改善推荐结果的注册用户
|
||||||
|
- 维护影片信息和推荐质量的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 用户可以完成浏览、评分、收藏闭环
|
||||||
|
- 系统可给出 TopN 推荐结果
|
||||||
|
- 推荐结果要有基础可解释性
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 注册/登录
|
||||||
|
- 电影列表和详情
|
||||||
|
- 搜索、分类、分页
|
||||||
|
- 用户评分
|
||||||
|
- 收藏电影
|
||||||
|
- 推荐页
|
||||||
|
- 管理后台维护电影数据
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 复杂协同过滤算法
|
||||||
|
- 视频播放
|
||||||
|
- 评论社区
|
||||||
|
- 多维画像系统
|
||||||
|
- 实时推荐流计算
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 游客 | 浏览电影列表与详情 |
|
||||||
|
| 注册用户 | 评分、收藏、查看推荐 |
|
||||||
|
| 管理员 | 管理电影数据、查看推荐概览 |
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
## 5.1 页面架构总览
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,9 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 用户前台 `5` 个大页面
|
||||||
|
- 后台管理台 `3` 个大页面
|
||||||
|
|
||||||
|
### A. 官网前台 `www.xxx.com`
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 产品介绍
|
||||||
|
- 热门电影
|
||||||
|
- 注册入口
|
||||||
|
|
||||||
|
### B. 用户前台 `app.xxx.com`
|
||||||
|
|
||||||
|
#### 2. 登录页 `app:/login`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 登录
|
||||||
|
- 注册入口
|
||||||
|
|
||||||
|
#### 3. 电影列表页 `app:/movies`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 浏览电影
|
||||||
|
- 搜索和筛选
|
||||||
|
- 分页
|
||||||
|
|
||||||
|
#### 4. 电影详情页 `app:/movies/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看海报和简介
|
||||||
|
- 评分
|
||||||
|
- 收藏
|
||||||
|
- 查看标签和推荐理由
|
||||||
|
|
||||||
|
#### 5. 推荐页 `app:/recommendations`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看个性化推荐
|
||||||
|
- 查看推荐理由
|
||||||
|
|
||||||
|
#### 6. 个人中心 `app:/me`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看评分历史
|
||||||
|
- 查看收藏
|
||||||
|
- 查看个人偏好
|
||||||
|
|
||||||
|
### C. 后台管理台 `admin.xxx.com`
|
||||||
|
|
||||||
|
#### 7. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 电影总数
|
||||||
|
- 用户行为概览
|
||||||
|
- 推荐效果概览
|
||||||
|
|
||||||
|
#### 8. 电影管理页 `admin:/movies`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 新增电影
|
||||||
|
- 编辑电影
|
||||||
|
- 管理标签
|
||||||
|
|
||||||
|
#### 9. 推荐概览页 `admin:/recommendations`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看推荐结果
|
||||||
|
- 查看热门标签
|
||||||
|
- 查看用户行为统计
|
||||||
|
|
||||||
|
## 5.2 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
visitor["访客"] --> list["电影列表页"]
|
||||||
|
list --> detail["电影详情页"]
|
||||||
|
visitor --> login["登录 / 注册"]
|
||||||
|
login --> rate["评分 / 收藏"]
|
||||||
|
rate --> reco["推荐页"]
|
||||||
|
reco --> me["个人中心"]
|
||||||
|
admin["管理员"] --> movies["电影管理页"]
|
||||||
|
movies --> recoAdmin["推荐概览页"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 用户:游客 -> 注册用户
|
||||||
|
- 电影交互:未评分 -> 已评分
|
||||||
|
- 推荐:冷启动 -> 有偏好推荐
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- React 或 Vue
|
||||||
|
- TypeScript
|
||||||
|
- Ant Design / shadcn/ui
|
||||||
|
|
||||||
|
建议页面:
|
||||||
|
|
||||||
|
| 页面 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 首页 | `/` | 热门电影、推荐入口 |
|
||||||
|
| 电影列表页 | `/movies` | 搜索、筛选、分页 |
|
||||||
|
| 电影详情页 | `/movies/:id` | 简介、标签、评分、收藏 |
|
||||||
|
| 推荐页 | `/recommendations` | 个性化推荐列表 |
|
||||||
|
| 个人中心 | `/me` | 评分与收藏记录 |
|
||||||
|
| 管理后台 | `/admin/movies` | 电影维护 |
|
||||||
|
|
||||||
|
前端关键组件:
|
||||||
|
|
||||||
|
- 电影卡片
|
||||||
|
- 搜索筛选栏
|
||||||
|
- 评分组件
|
||||||
|
- 收藏按钮
|
||||||
|
- 推荐理由展示卡片
|
||||||
|
- 后台表格和编辑弹窗
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Java 17
|
||||||
|
- Spring Boot 3
|
||||||
|
- Spring Web
|
||||||
|
- Spring Data JPA
|
||||||
|
- MySQL 8
|
||||||
|
- JWT 鉴权
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `auth`
|
||||||
|
- `movies`
|
||||||
|
- `ratings`
|
||||||
|
- `favorites`
|
||||||
|
- `recommendations`
|
||||||
|
- `admin`
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
users (
|
||||||
|
id bigint primary key auto_increment,
|
||||||
|
email varchar(120),
|
||||||
|
password_hash varchar(255),
|
||||||
|
role varchar(20),
|
||||||
|
created_at datetime
|
||||||
|
)
|
||||||
|
|
||||||
|
movies (
|
||||||
|
id bigint primary key auto_increment,
|
||||||
|
title varchar(200),
|
||||||
|
summary text,
|
||||||
|
release_year int,
|
||||||
|
poster_url varchar(500),
|
||||||
|
created_at datetime
|
||||||
|
)
|
||||||
|
|
||||||
|
movie_tags (
|
||||||
|
id bigint primary key auto_increment,
|
||||||
|
movie_id bigint,
|
||||||
|
tag varchar(50)
|
||||||
|
)
|
||||||
|
|
||||||
|
ratings (
|
||||||
|
id bigint primary key auto_increment,
|
||||||
|
user_id bigint,
|
||||||
|
movie_id bigint,
|
||||||
|
score int,
|
||||||
|
created_at datetime
|
||||||
|
)
|
||||||
|
|
||||||
|
favorites (
|
||||||
|
id bigint primary key auto_increment,
|
||||||
|
user_id bigint,
|
||||||
|
movie_id bigint,
|
||||||
|
created_at datetime
|
||||||
|
)
|
||||||
|
|
||||||
|
recommendation_logs (
|
||||||
|
id bigint primary key auto_increment,
|
||||||
|
user_id bigint,
|
||||||
|
strategy varchar(50),
|
||||||
|
result_count int,
|
||||||
|
created_at datetime
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 电影总数
|
||||||
|
- 日评分数
|
||||||
|
- 收藏率
|
||||||
|
- 推荐点击率
|
||||||
|
- 热门标签分布
|
||||||
|
- 冷启动用户占比
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- 推荐接口响应耗时
|
||||||
|
- 评分写入成功率
|
||||||
|
- 数据库慢查询
|
||||||
|
- 缓存命中率(如果用了 Redis)
|
||||||
|
|
||||||
|
## 7. 推荐策略
|
||||||
|
|
||||||
|
第一版推荐策略建议:
|
||||||
|
|
||||||
|
- 基于标签偏好
|
||||||
|
- 结合用户评分权重
|
||||||
|
- 冷启动时叠加热门电影
|
||||||
|
- 过滤已评分/已收藏电影
|
||||||
|
|
||||||
|
推荐结果应展示:
|
||||||
|
|
||||||
|
- 推荐分值
|
||||||
|
- 推荐理由
|
||||||
|
- 对应标签
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/auth/register` | 注册 |
|
||||||
|
| `POST` | `/api/auth/login` | 登录 |
|
||||||
|
| `GET` | `/api/movies` | 电影列表,支持搜索与分页 |
|
||||||
|
| `GET` | `/api/movies/:id` | 电影详情 |
|
||||||
|
| `POST` | `/api/movies/:id/ratings` | 提交评分 |
|
||||||
|
| `POST` | `/api/movies/:id/favorite` | 收藏电影 |
|
||||||
|
| `DELETE` | `/api/movies/:id/favorite` | 取消收藏 |
|
||||||
|
| `GET` | `/api/recommendations` | 获取推荐结果 |
|
||||||
|
| `GET` | `/api/me/profile` | 获取用户资料和行为摘要 |
|
||||||
|
| `POST` | `/api/admin/movies` | 新增电影 |
|
||||||
|
| `PATCH` | `/api/admin/movies/:id` | 编辑电影 |
|
||||||
|
|
||||||
|
`GET /api/recommendations` 返回示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"movieId": 12,
|
||||||
|
"title": "Interstellar",
|
||||||
|
"score": 0.91,
|
||||||
|
"reason": "你近期给高分的科幻与冒险标签影片较多"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. 关键业务规则
|
||||||
|
|
||||||
|
- 每个用户对同一电影只保留一条评分
|
||||||
|
- 收藏与评分都能影响推荐
|
||||||
|
- 管理员接口必须单独鉴权
|
||||||
|
- 推荐结果至少返回 10 条或当前可用最大值
|
||||||
|
|
||||||
|
## 10. 非功能要求
|
||||||
|
|
||||||
|
- 推荐结果应可解释
|
||||||
|
- 列表与详情页加载要可接受
|
||||||
|
- 管理员接口与普通用户接口权限严格分离
|
||||||
|
- 推荐缓存和行为数据允许后续扩展
|
||||||
|
|
||||||
|
## 11. 开发顺序建议
|
||||||
|
|
||||||
|
1. 登录与用户体系
|
||||||
|
2. 电影列表与详情
|
||||||
|
3. 评分与收藏
|
||||||
|
4. 推荐接口
|
||||||
|
5. 后台管理页
|
||||||
|
|
||||||
|
## 12. 待确认项
|
||||||
|
|
||||||
|
- 前端选 React 还是 Vue
|
||||||
|
- 推荐解释文案是后端拼接还是前端渲染
|
||||||
|
- 是否需要影片导入脚本
|
||||||
|
- 后台是否要包含标签管理
|
||||||
@@ -1,294 +1,119 @@
|
|||||||
# 电影推荐网 (Spring Boot)
|
# Spring Boot 电影推荐系统开发实战
|
||||||
|
|
||||||
推荐系统是最典型的“看起来简单,做起来很像真实业务系统”的题目。
|
这个项目不是“做一个电影列表页”,而是围绕一份真实 PRD,把一个带推荐能力的内容产品从想法推进到可上线原型。
|
||||||
|
|
||||||
这次大作业你会从“电影列表网站”升级到“可登录、可评分、可推荐、可管理”的完整产品原型。
|
你会同时看到三件事:
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
- 项目要做成什么
|
||||||
打造一个 **电影推荐网站(Spring Boot)**。用户登录后可浏览电影、搜索筛选、评分收藏,并获得个性化推荐;管理员可维护电影数据、查看用户行为统计与推荐效果。
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
|
::: tip PRD 入口
|
||||||
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定边界', description: '先锁定推荐策略和第一版业务范围' },
|
{ title: '看 PRD', description: '先明确页面、评分收藏、推荐逻辑和后台范围' },
|
||||||
{ title: '搭基础', description: '先做用户、电影、评分这些核心页面' },
|
{ title: '生成骨架', description: '让 AI 先产出列表页、详情页、推荐页和后台页骨架' },
|
||||||
{ title: '做推荐', description: '接通 Spring Boot 接口与推荐逻辑' },
|
{ title: '监工迭代', description: '逐页验收、补接口、修推荐逻辑和数据链路' },
|
||||||
{ title: '上线交付', description: '补齐后台、部署和演示材料' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的推荐系统原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个题目适合 Stage 2?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
因为它能一次性把你带过 5 个关键能力:
|
这是一个带推荐能力的电影网站:
|
||||||
|
|
||||||
- **后端工程化**:Controller / Service / Repository 分层
|
- 用户可以浏览、搜索、评分、收藏电影
|
||||||
- **数据建模**:用户、电影、标签、评分、推荐结果
|
- 系统根据用户行为给出推荐结果
|
||||||
- **业务逻辑**:搜索筛选、评分行为、收藏与历史
|
- 管理员可以维护电影数据和查看推荐效果
|
||||||
- **推荐算法入门**:规则推荐或协同过滤
|
|
||||||
- **管理能力**:后台维护数据与查看指标
|
|
||||||
|
|
||||||
做完后你不仅能讲“我写了个网站”,还能讲清楚“推荐是怎么跑起来的”。
|
## 开发过程怎么走?
|
||||||
|
|
||||||
## 先看系统全景
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
```mermaid
|
先确认:
|
||||||
flowchart LR
|
|
||||||
user["用户端"] --> fe["Web 前端"]
|
|
||||||
admin["管理员"] --> adminfe["后台页面"]
|
|
||||||
fe --> api["Spring Boot API"]
|
|
||||||
adminfe --> api
|
|
||||||
api --> mysql["MySQL"]
|
|
||||||
api --> redis["Redis (可选缓存)"]
|
|
||||||
api --> rec["推荐服务层"]
|
|
||||||
rec --> feature["用户偏好特征"]
|
|
||||||
rec --> movieFeature["电影标签特征"]
|
|
||||||
rec --> result["推荐结果"]
|
|
||||||
result --> fe
|
|
||||||
```
|
|
||||||
|
|
||||||
```mermaid
|
- 推荐策略是不是先用可解释版本
|
||||||
sequenceDiagram
|
- 页面和后台范围是否拍板
|
||||||
autonumber
|
- 用户行为数据要存哪些
|
||||||
actor U as 用户
|
- 管理员要看哪些推荐效果指标
|
||||||
participant FE as 前端
|
|
||||||
participant API as Spring Boot
|
|
||||||
participant REC as 推荐模块
|
|
||||||
participant DB as MySQL
|
|
||||||
|
|
||||||
U->>FE: 浏览电影并评分
|
### 2. 先让 AI 生成“骨架版”
|
||||||
FE->>API: POST /api/ratings
|
|
||||||
API->>DB: 写入评分记录
|
|
||||||
U->>FE: 打开“为你推荐”
|
|
||||||
FE->>API: GET /api/recommendations
|
|
||||||
API->>REC: 计算推荐候选
|
|
||||||
REC->>DB: 读取用户偏好与电影标签
|
|
||||||
DB-->>REC: 返回特征数据
|
|
||||||
REC-->>API: 返回推荐列表
|
|
||||||
API-->>FE: 返回电影卡片数据
|
|
||||||
```
|
|
||||||
|
|
||||||
## 1. 定边界:别一上来就做“工业级推荐系统”
|
第一轮先生成:
|
||||||
|
|
||||||
### 角色设计
|
|
||||||
|
|
||||||
| 角色 | 核心动作 |
|
|
||||||
|------|------|
|
|
||||||
| 普通用户 | 注册登录、浏览电影、搜索筛选、评分收藏、查看推荐 |
|
|
||||||
| 管理员 | 电影信息管理、标签管理、用户行为统计、推荐结果抽查 |
|
|
||||||
|
|
||||||
### 核心页面规划
|
|
||||||
|
|
||||||
| 页面 | 路径 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| 首页 | `/` | 热门电影与推荐入口 |
|
|
||||||
| 登录/注册 | `/login` `/register` | 用户认证 |
|
|
||||||
| 电影列表 | `/movies` | 搜索、筛选、分页 |
|
|
||||||
| 电影详情 | `/movies/:id` | 简介、标签、评分、评论 |
|
|
||||||
| 推荐页 | `/recommendations` | 个性化推荐结果 |
|
|
||||||
| 收藏页 | `/favorites` | 收藏电影管理 |
|
|
||||||
| 管理后台 | `/admin` | 电影与标签维护、统计看板 |
|
|
||||||
|
|
||||||
### 第一版推荐策略(建议)
|
|
||||||
|
|
||||||
第一版只做一套简单但稳定的推荐规则:
|
|
||||||
|
|
||||||
- 基于用户历史评分的 **标签偏好加权**
|
|
||||||
- 再叠加热门度分数(避免冷启动全空)
|
|
||||||
- 去掉用户已看/已评分电影
|
|
||||||
|
|
||||||
先把可解释、可跑通的推荐做出来,比复杂算法更重要。
|
|
||||||
|
|
||||||
## 2. 搭基础:先完成“非推荐功能闭环”
|
|
||||||
|
|
||||||
### 推荐技术栈
|
|
||||||
|
|
||||||
- 后端:Spring Boot 3 + Spring Web + Spring Data JPA
|
|
||||||
- 数据库:MySQL 8
|
|
||||||
- 缓存:Redis(可选)
|
|
||||||
- 前端:Vue/React 任一(可由 AI IDE 生成)
|
|
||||||
- 鉴权:JWT
|
|
||||||
|
|
||||||
### 数据模型建议
|
|
||||||
|
|
||||||
```sql
|
|
||||||
users (
|
|
||||||
id bigint primary key auto_increment,
|
|
||||||
email varchar(120),
|
|
||||||
password_hash varchar(255),
|
|
||||||
role varchar(20), -- user / admin
|
|
||||||
created_at datetime
|
|
||||||
)
|
|
||||||
|
|
||||||
movies (
|
|
||||||
id bigint primary key auto_increment,
|
|
||||||
title varchar(200),
|
|
||||||
summary text,
|
|
||||||
release_year int,
|
|
||||||
poster_url varchar(500),
|
|
||||||
created_at datetime
|
|
||||||
)
|
|
||||||
|
|
||||||
movie_tags (
|
|
||||||
id bigint primary key auto_increment,
|
|
||||||
movie_id bigint,
|
|
||||||
tag varchar(50)
|
|
||||||
)
|
|
||||||
|
|
||||||
ratings (
|
|
||||||
id bigint primary key auto_increment,
|
|
||||||
user_id bigint,
|
|
||||||
movie_id bigint,
|
|
||||||
score int, -- 1~5
|
|
||||||
created_at datetime
|
|
||||||
)
|
|
||||||
|
|
||||||
favorites (
|
|
||||||
id bigint primary key auto_increment,
|
|
||||||
user_id bigint,
|
|
||||||
movie_id bigint,
|
|
||||||
created_at datetime
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第一步:用 AI IDE 生成 Spring Boot 骨架
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我搭建一个 Spring Boot 电影推荐网站后端骨架。
|
|
||||||
|
|
||||||
要求:
|
|
||||||
- Java 17 + Spring Boot 3
|
|
||||||
- 分层结构:controller / service / repository / model / dto
|
|
||||||
- MySQL + JPA
|
|
||||||
- JWT 登录鉴权
|
|
||||||
|
|
||||||
接口优先实现:
|
|
||||||
1. 用户注册登录
|
|
||||||
2. 电影列表查询(分页+关键词)
|
|
||||||
3. 电影详情
|
|
||||||
4. 用户评分
|
|
||||||
5. 收藏与取消收藏
|
|
||||||
|
|
||||||
请先给出目录结构和关键类清单,再逐步生成代码。
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第二步:补齐前端基础页面
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我生成一个电影推荐网站前端页面骨架。
|
|
||||||
|
|
||||||
页面包括:
|
|
||||||
- 首页
|
- 首页
|
||||||
- 电影列表页(筛选+分页)
|
- 电影列表页
|
||||||
- 电影详情页(评分+收藏)
|
- 电影详情页
|
||||||
- 推荐页
|
- 推荐页
|
||||||
- 个人中心
|
- 个人中心
|
||||||
- 管理后台
|
- 管理后台
|
||||||
|
|
||||||
要求:
|
### 3. 再进入“监工模式”
|
||||||
- 组件化开发
|
|
||||||
- 有 loading、空态、错误提示
|
|
||||||
- 先接 mock 接口,再切换真实 API
|
|
||||||
```
|
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
你要重点盯这几件事:
|
||||||
<ClientOnly>
|
|
||||||
<StepBar :active="1" :items="[
|
|
||||||
{ title: '定边界', description: '先锁定推荐策略和第一版业务范围' },
|
|
||||||
{ title: '搭基础', description: '先做用户、电影、评分这些核心页面' },
|
|
||||||
{ title: '做推荐', description: '接通 Spring Boot 接口与推荐逻辑' },
|
|
||||||
{ title: '上线交付', description: '补齐后台、部署和演示材料' }
|
|
||||||
]" />
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 3. 做推荐:先做“可解释推荐”,再做“更聪明推荐”
|
- 列表、详情、评分、收藏是不是闭环
|
||||||
|
- 推荐结果是不是和行为数据联动
|
||||||
|
- 推荐理由是不是可解释
|
||||||
|
- 后台电影数据和用户行为是不是能查看
|
||||||
|
|
||||||
### 推荐模块拆分建议
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
| 模块 | 职责 |
|
|
||||||
|------|------|
|
|
||||||
| CandidateService | 召回候选电影(未看、同标签、热门) |
|
|
||||||
| RankingService | 按偏好分数排序并截断 TopN |
|
|
||||||
| ExplainService | 生成“为什么推荐这部电影”文案 |
|
|
||||||
| RecommendationController | 对外提供推荐接口 |
|
|
||||||
|
|
||||||
### 推荐流程图
|
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["读取用户评分历史"] --> B["统计用户标签偏好"]
|
prd["PRD"] --> web["前端页面"]
|
||||||
B --> C["召回候选电影"]
|
web --> auth["用户鉴权"]
|
||||||
C --> D["计算综合分数"]
|
web --> movie["电影列表 / 详情"]
|
||||||
D --> E["过滤已看电影"]
|
web --> behavior["评分 / 收藏"]
|
||||||
E --> F["生成 Top N 推荐"]
|
behavior --> reco["推荐逻辑"]
|
||||||
F --> G["返回推荐原因与标签命中"]
|
reco --> db["数据库"]
|
||||||
|
admin["后台管理"] --> db
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第三步:让 AI IDE 帮你实现推荐接口
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我实现 Spring Boot 推荐接口 GET /api/recommendations。
|
请基于当前 PRD,帮我生成一个 Spring Boot 电影推荐系统的前端骨架。
|
||||||
|
|
||||||
业务规则:
|
|
||||||
1. 根据用户最近评分记录统计偏好标签权重
|
|
||||||
2. 从同标签电影中召回候选
|
|
||||||
3. 结合全站热门度做加权
|
|
||||||
4. 去掉用户已经评分过的电影
|
|
||||||
5. 返回前 12 条推荐,并附带推荐理由
|
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
- Service 层拆分清晰
|
1. 页面包括:首页、电影列表、电影详情、推荐页、个人中心、后台管理
|
||||||
- SQL 或 JPA 查询可读
|
2. 先只生成页面结构和假数据,不接真实接口
|
||||||
- 返回结构包含 movieId、title、score、reason
|
3. 风格要像真实内容产品,而不是课堂 demo
|
||||||
- 给出最小可跑通的单元测试示例
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第四步:补管理员统计页
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
第一版至少展示这些指标:
|
| 检查项 | 要看什么 |
|
||||||
|
|------|------|
|
||||||
|
| 页面是否对 | 页面数量、功能是否符合 PRD |
|
||||||
|
| 接口是否对 | movies、ratings、favorites、recommendations 是否闭环 |
|
||||||
|
| 数据是否对 | 用户行为是否影响推荐结果 |
|
||||||
|
| 推荐是否对 | 推荐理由是否清晰、结果是否可解释 |
|
||||||
|
| 演示是否对 | 是否能演示“浏览 -> 评分 -> 推荐变化” |
|
||||||
|
|
||||||
- 总用户数
|
## 最后的预期效果
|
||||||
- 总电影数
|
|
||||||
- 最近 7 天评分次数
|
|
||||||
- 推荐接口成功率与平均耗时
|
|
||||||
|
|
||||||
这样你可以快速发现系统是否健康,而不是“看起来能用但实际经常失败”。
|
- 一套可运行的电影推荐系统
|
||||||
|
- 一份同级 PRD 文档
|
||||||
|
- 浏览、评分、收藏、推荐、后台管理
|
||||||
|
- Spring Boot 后端与推荐逻辑
|
||||||
|
- README 和演示方案
|
||||||
|
|
||||||
## 4. 上线与交付
|
## 验收标准
|
||||||
|
|
||||||
### 交付物
|
| 维度 | 最低达标 |
|
||||||
|
|------|------|
|
||||||
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
|
| 产品闭环 | 浏览、评分、收藏、推荐可以跑通 |
|
||||||
|
| 后台能力 | 电影数据和推荐效果可查看 |
|
||||||
|
| 工程完整度 | 前端、后端、数据库、推荐接口已接通 |
|
||||||
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
- Spring Boot 后端仓库(含数据库初始化脚本)
|
::: tip 🚀 完成后你会得到什么?
|
||||||
- 前端项目仓库(或单仓 monorepo)
|
你得到的不只是一个电影站,而是一套“内容 + 行为 + 推荐”型产品的开发样例。
|
||||||
- 可访问演示地址
|
:::
|
||||||
- README(本地启动、环境变量、部署方式)
|
|
||||||
- 60 秒演示视频
|
|
||||||
|
|
||||||
### 验收标准
|
|
||||||
|
|
||||||
| 维度 | 最低达标 | 加分项 |
|
|
||||||
|------|------|------|
|
|
||||||
| 基础功能 | 注册登录、电影浏览、评分收藏都可用 | 评论、观看历史等拓展功能 |
|
|
||||||
| 推荐质量 | 推荐列表可生成且有理由 | 支持冷启动策略与个性化解释 |
|
|
||||||
| 工程质量 | 接口分层清晰,错误可追踪 | 有单测与缓存优化 |
|
|
||||||
| 管理能力 | 管理员可维护电影和标签 | 有统计看板和告警阈值 |
|
|
||||||
| 交付能力 | 可部署、文档完整、可复现 | CI/CD 或自动化脚本 |
|
|
||||||
|
|
||||||
## 提交前最后检查
|
|
||||||
|
|
||||||
<el-card shadow="hover" style="margin: 20px 0; border-radius: 12px;">
|
|
||||||
<template #header>
|
|
||||||
<div style="font-weight: bold; font-size: 16px;">提交前最后看一眼</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<ul style="list-style-type: none; padding-left: 0;">
|
|
||||||
<li><label><input type="checkbox" disabled /> 用户可注册登录并浏览电影</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 评分与收藏数据已写入数据库</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 推荐页能返回个性化结果</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 推荐结果包含“推荐理由”字段</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 管理后台可维护电影与标签</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 项目可部署且 README 可复现</label></li>
|
|
||||||
</ul>
|
|
||||||
</el-card>
|
|
||||||
|
|||||||
@@ -0,0 +1,393 @@
|
|||||||
|
# PRD:生鲜电商微服务系统
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:先明确服务拆分、数据边界和交易主链路,再进入开发。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个用来练微服务拆分和服务协作的电商系统。重点不是做复杂运营功能,而是跑通:
|
||||||
|
|
||||||
|
- 商品浏览
|
||||||
|
- 下单
|
||||||
|
- 扣库存
|
||||||
|
- 查订单
|
||||||
|
- 管理端调库存
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个由网关、鉴权、商品、库存、订单协作完成交易闭环的生鲜电商微服务系统。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
WWW["www.xxx.com<br/>官网前台"] --> GW["API Gateway"]
|
||||||
|
APP["app.xxx.com<br/>用户前台"] --> GW
|
||||||
|
ADMIN["admin.xxx.com<br/>后台管理台"] --> GW
|
||||||
|
GW --> AUTH["Auth Service"]
|
||||||
|
GW --> CATALOG["Catalog Service"]
|
||||||
|
GW --> INVENTORY["Inventory Service"]
|
||||||
|
GW --> ORDER["Order Service"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.0 技术选型建议
|
||||||
|
|
||||||
|
- 前端框架:`Next.js`
|
||||||
|
- 网关:`Node.js + Express/Fastify`
|
||||||
|
- 服务层:`Node.js + Express/Fastify`
|
||||||
|
- 数据库:`PostgreSQL`
|
||||||
|
- 鉴权:`JWT`
|
||||||
|
- 编排:`Docker Compose`
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 用户前台:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.1 竞品参考(官方)
|
||||||
|
|
||||||
|
- [Instacart](https://www.instacart.com/)
|
||||||
|
|
||||||
|
## 1.2 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考真实生鲜电商产品:
|
||||||
|
|
||||||
|
- 借鉴 `Instacart` 的用户购物路径:从商品浏览到购物车、订单查看都应足够直接
|
||||||
|
- 商品页和购物车页应强调价格、库存状态和操作反馈
|
||||||
|
- 管理端页面应更像运营后台,突出商品、库存、订单状态管理
|
||||||
|
- 前台页面不需要做得很复杂,但一定要把“下单链路”做顺
|
||||||
|
- 微服务拆分服务于业务边界,前端体验要尽量像统一产品,而不是几个接口拼起来
|
||||||
|
|
||||||
|
## 1.3 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `Instacart` 首页与商品分类页
|
||||||
|
- 重点看:分类、商品卡片、购物入口的清晰程度
|
||||||
|
- `Instacart` 购物车与结算体验
|
||||||
|
- 重点看:从商品到下单的路径是否顺畅
|
||||||
|
- 电商后台常见商品/订单管理思路
|
||||||
|
- 重点看:列表、状态筛选、库存调整这些基础运营动作
|
||||||
|
|
||||||
|
因此本项目建议:
|
||||||
|
|
||||||
|
- 用户端更强调“快速下单”
|
||||||
|
- 管理端更强调“状态管理”
|
||||||
|
- 微服务架构隐藏在后台,前台体验仍应统一
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 浏览商品并下单的普通用户
|
||||||
|
- 调整商品与库存的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 用户下单链路完整可追踪
|
||||||
|
- 库存与订单状态一致
|
||||||
|
- 每个服务边界清晰,可独立维护
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- API Gateway
|
||||||
|
- Auth 服务
|
||||||
|
- Catalog 服务
|
||||||
|
- Inventory 服务
|
||||||
|
- Order 服务
|
||||||
|
- 用户端商品列表/详情/下单
|
||||||
|
- 管理端商品与库存管理
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 真实支付
|
||||||
|
- 优惠券和促销
|
||||||
|
- 秒杀
|
||||||
|
- 消息队列集群
|
||||||
|
- 分布式事务框架
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 普通用户 | 浏览商品、下单、查看自己的订单 |
|
||||||
|
| 管理员 | 商品上下架、库存调整、查看订单 |
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
## 5.1 页面架构总览
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,9 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 用户前台 `4` 个大页面
|
||||||
|
- 后台管理台 `4` 个大页面
|
||||||
|
|
||||||
|
### A. 官网前台 `www.xxx.com`
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 品类入口
|
||||||
|
- 活动区
|
||||||
|
- 登录入口
|
||||||
|
|
||||||
|
### B. 用户前台 `app.xxx.com`
|
||||||
|
|
||||||
|
#### 2. 商品列表页 `app:/products`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 浏览分类
|
||||||
|
- 查看商品卡片
|
||||||
|
- 加入购物车
|
||||||
|
|
||||||
|
#### 3. 商品详情页 `app:/products/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看商品详情
|
||||||
|
- 查看库存状态
|
||||||
|
- 加入购物车
|
||||||
|
|
||||||
|
#### 4. 购物车页 `app:/cart`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看购物车
|
||||||
|
- 修改数量
|
||||||
|
- 提交订单
|
||||||
|
|
||||||
|
#### 5. 订单页 `app:/orders`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看我的订单
|
||||||
|
- 查看订单状态
|
||||||
|
|
||||||
|
### C. 后台管理台 `admin.xxx.com`
|
||||||
|
|
||||||
|
#### 6. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 商品数
|
||||||
|
- 库存预警
|
||||||
|
- 订单概览
|
||||||
|
|
||||||
|
#### 7. 商品管理页 `admin:/products`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 上下架商品
|
||||||
|
- 编辑价格与分类
|
||||||
|
|
||||||
|
#### 8. 库存管理页 `admin:/inventory`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看库存
|
||||||
|
- 调整库存
|
||||||
|
|
||||||
|
#### 9. 订单管理页 `admin:/orders`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看订单
|
||||||
|
- 筛选状态
|
||||||
|
|
||||||
|
## 5.2 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
user["用户"] --> products["商品列表"]
|
||||||
|
products --> detail["商品详情"]
|
||||||
|
detail --> cart["购物车"]
|
||||||
|
cart --> order["提交订单"]
|
||||||
|
order --> inventory["库存扣减"]
|
||||||
|
inventory --> orders["我的订单"]
|
||||||
|
admin["管理员"] --> inventoryAdmin["库存管理"]
|
||||||
|
admin --> orderAdmin["订单管理"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 订单:待创建 -> 已创建 -> 已完成 / 已取消
|
||||||
|
- 库存:可用 -> 预扣 -> 确认扣减 / 回滚
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Next.js
|
||||||
|
- TypeScript
|
||||||
|
- Tailwind CSS
|
||||||
|
|
||||||
|
建议页面:
|
||||||
|
|
||||||
|
| 页面 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 首页 | `/` | 商品列表与分类 |
|
||||||
|
| 商品详情 | `/products/:id` | 商品信息与加入购物车 |
|
||||||
|
| 购物车 | `/cart` | 确认下单 |
|
||||||
|
| 我的订单 | `/orders` | 查看订单历史 |
|
||||||
|
| 管理后台商品页 | `/admin/products` | 商品维护 |
|
||||||
|
| 管理后台库存页 | `/admin/inventory` | 库存调整 |
|
||||||
|
| 管理后台订单页 | `/admin/orders` | 订单列表与状态 |
|
||||||
|
|
||||||
|
前端关键组件:
|
||||||
|
|
||||||
|
- 商品卡片
|
||||||
|
- 购物车抽屉/页面
|
||||||
|
- 订单状态标签
|
||||||
|
- 管理后台表格
|
||||||
|
- 库存调整弹窗
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Node.js + Express/Fastify
|
||||||
|
- PostgreSQL
|
||||||
|
- Docker Compose
|
||||||
|
|
||||||
|
服务拆分:
|
||||||
|
|
||||||
|
| 服务 | 职责 |
|
||||||
|
|------|------|
|
||||||
|
| `api-gateway` | 统一路由、鉴权、聚合返回 |
|
||||||
|
| `auth-service` | 注册、登录、JWT 校验 |
|
||||||
|
| `catalog-service` | 商品信息、分类、上下架 |
|
||||||
|
| `inventory-service` | 库存查询、预扣、回滚 |
|
||||||
|
| `order-service` | 订单创建、状态流转、查询 |
|
||||||
|
|
||||||
|
建议数据模型:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
users (
|
||||||
|
id uuid primary key,
|
||||||
|
email text,
|
||||||
|
password_hash text,
|
||||||
|
role text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
products (
|
||||||
|
id uuid primary key,
|
||||||
|
name text,
|
||||||
|
category text,
|
||||||
|
price_cents int,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
inventory_items (
|
||||||
|
id uuid primary key,
|
||||||
|
product_id uuid,
|
||||||
|
available_quantity int,
|
||||||
|
reserved_quantity int,
|
||||||
|
updated_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
orders (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
total_amount_cents int,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
order_items (
|
||||||
|
id uuid primary key,
|
||||||
|
order_id uuid,
|
||||||
|
product_id uuid,
|
||||||
|
quantity int,
|
||||||
|
price_cents int
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 下单成功率
|
||||||
|
- 库存回滚次数
|
||||||
|
- 热销商品排行
|
||||||
|
- 订单状态分布
|
||||||
|
- 库存预警数
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- 网关错误率
|
||||||
|
- 鉴权服务成功率
|
||||||
|
- 库存服务超时率
|
||||||
|
- 订单创建失败率
|
||||||
|
|
||||||
|
## 7. 下单主链路
|
||||||
|
|
||||||
|
主流程:
|
||||||
|
|
||||||
|
1. 用户提交订单
|
||||||
|
2. Gateway 完成鉴权
|
||||||
|
3. Order 服务校验商品
|
||||||
|
4. Inventory 服务预扣库存
|
||||||
|
5. Order 服务创建订单
|
||||||
|
6. 成功则确认库存,失败则补偿回滚
|
||||||
|
|
||||||
|
关键规则:
|
||||||
|
|
||||||
|
- 库存不足直接失败
|
||||||
|
- 同一个订单只允许一次成功创建
|
||||||
|
- 所有状态变化要可追踪
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
外部接口统一走 Gateway:
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/auth/register` | 注册 |
|
||||||
|
| `POST` | `/api/auth/login` | 登录 |
|
||||||
|
| `GET` | `/api/catalog/products` | 商品列表 |
|
||||||
|
| `GET` | `/api/catalog/products/:id` | 商品详情 |
|
||||||
|
| `POST` | `/api/orders` | 创建订单 |
|
||||||
|
| `GET` | `/api/orders/my` | 当前用户订单列表 |
|
||||||
|
| `GET` | `/api/orders/:id` | 订单详情 |
|
||||||
|
| `PATCH` | `/api/inventory/:productId` | 管理员调整库存 |
|
||||||
|
| `POST` | `/api/admin/products` | 管理员新增商品 |
|
||||||
|
| `PATCH` | `/api/admin/products/:id` | 管理员编辑商品 |
|
||||||
|
|
||||||
|
`POST /api/orders` 请求示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{ "productId": "p1", "quantity": 2 },
|
||||||
|
{ "productId": "p2", "quantity": 1 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. 非功能要求
|
||||||
|
|
||||||
|
- 本地一键启动
|
||||||
|
- 服务之间日志可追踪
|
||||||
|
- 接口返回结构统一
|
||||||
|
- 关键链路有错误处理和补偿逻辑
|
||||||
|
|
||||||
|
## 10. 开发顺序建议
|
||||||
|
|
||||||
|
1. Monorepo/Workspaces 与 Gateway
|
||||||
|
2. Auth 服务
|
||||||
|
3. Catalog 与 Inventory
|
||||||
|
4. Order 下单闭环
|
||||||
|
5. 前端用户端与管理端
|
||||||
|
6. Docker Compose 与文档
|
||||||
|
|
||||||
|
## 11. 待确认项
|
||||||
|
|
||||||
|
- 前端是否做购物车持久化
|
||||||
|
- 服务间通信先用 HTTP 还是预留消息机制
|
||||||
|
- 商品与库存是否拆独立数据库
|
||||||
|
- 管理端是否允许直接修改订单状态
|
||||||
@@ -1,253 +1,119 @@
|
|||||||
# 简单买菜微服务网站
|
# 生鲜电商微服务系统开发实战
|
||||||
|
|
||||||
做完单体应用后,很多同学会进入一个新困惑:功能越来越多,代码还能写,但项目越来越难维护。
|
这个项目不是“做一个买菜网站”,而是围绕一份真实 PRD,把一个微服务电商系统从想法推进到可运行原型。
|
||||||
|
|
||||||
这个大作业的目标,就是让你在一个可控规模里,体验一次“从单体到微服务”的完整过程。
|
你会同时看到三件事:
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
- 项目要做成什么
|
||||||
打造一个 **简单买菜微服务网站**。用户可以浏览商品、下单、查看订单;管理员可以管理商品与库存。后端拆成多个服务,通过 API 网关统一对外提供接口。
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
|
::: tip PRD 入口
|
||||||
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定边界', description: '先明确服务拆分和业务范围' },
|
{ title: '看 PRD', description: '先明确服务拆分、页面、交易链路和补偿策略' },
|
||||||
{ title: '搭基础', description: '网关、鉴权、数据库连接先跑通' },
|
{ title: '生成骨架', description: '让 AI 先产出前端、网关和服务骨架' },
|
||||||
{ title: '接业务', description: '商品、订单、库存链路打通' },
|
{ title: '监工迭代', description: '逐模块验收、补接口、修库存与订单一致性' },
|
||||||
{ title: '交付上线', description: '部署、文档、演示材料补齐' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的微服务原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个项目值得做?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
这个题目看起来是“买菜网站”,本质上练的是三个能力:
|
这是一个生鲜电商微服务系统:
|
||||||
|
|
||||||
- **拆服务**:学会按业务边界拆分,而不是按技术层硬拆
|
- 用户端负责浏览商品、下单、查看订单
|
||||||
- **控复杂度**:在多服务协作下保持清晰的接口和数据流
|
- 管理端负责商品、库存和订单管理
|
||||||
- **做稳定链路**:让“下单 -> 扣库存 -> 查订单”能够稳定可追踪
|
- 后端按业务拆成网关、鉴权、商品、库存、订单服务
|
||||||
|
|
||||||
这会直接影响你后续做电商、SaaS 后台、内容平台等多模块项目的上限。
|
## 开发过程怎么走?
|
||||||
|
|
||||||
## 先看全景:系统由哪些模块组成?
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
```mermaid
|
先确认:
|
||||||
flowchart LR
|
|
||||||
user["用户端 Web"] --> gateway["API Gateway"]
|
|
||||||
admin["管理端 Web"] --> gateway
|
|
||||||
gateway --> auth["Auth 服务"]
|
|
||||||
gateway --> catalog["商品服务"]
|
|
||||||
gateway --> order["订单服务"]
|
|
||||||
gateway --> inventory["库存服务"]
|
|
||||||
order --> inventory
|
|
||||||
catalog --> db1["Catalog DB"]
|
|
||||||
order --> db2["Order DB"]
|
|
||||||
inventory --> db3["Inventory DB"]
|
|
||||||
auth --> db4["User DB"]
|
|
||||||
```
|
|
||||||
|
|
||||||
这张图的核心意思是:前端不用直接找多个服务,只和网关交互。复杂性由网关和服务间协作承担。
|
- 服务拆分是否拍板
|
||||||
|
- 前台和管理端页面是否清楚
|
||||||
|
- 下单、库存扣减和补偿策略是否明确
|
||||||
|
- 第一版哪些复杂能力先不做
|
||||||
|
|
||||||
## 1. 定边界:先把范围控制住
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
### 建议服务拆分
|
第一轮先生成:
|
||||||
|
|
||||||
第一版只保留 4 个核心服务:
|
- 用户端首页、商品页、购物车、订单页
|
||||||
|
- 管理端商品、库存、订单管理页
|
||||||
|
- API Gateway
|
||||||
|
- auth、catalog、inventory、order 四个服务骨架
|
||||||
|
|
||||||
| 服务 | 职责 |
|
### 3. 再进入“监工模式”
|
||||||
|------|------|
|
|
||||||
| `auth-service` | 登录、注册、令牌校验、角色识别 |
|
|
||||||
| `catalog-service` | 商品列表、商品详情、分类查询 |
|
|
||||||
| `inventory-service` | 库存查询、库存扣减、库存回滚 |
|
|
||||||
| `order-service` | 创建订单、查询订单、订单状态管理 |
|
|
||||||
|
|
||||||
### 建议角色与页面
|
你要重点盯这几件事:
|
||||||
|
|
||||||
| 角色 | 页面 | 关键动作 |
|
- 网关路由是否正确
|
||||||
|------|------|------|
|
- JWT 和角色权限是否正确
|
||||||
| 用户 | 首页、商品页、购物车、订单页 | 浏览商品、下单、看订单 |
|
- 商品和库存数据是否一致
|
||||||
| 管理员 | 商品管理、库存管理、订单管理 | 上下架商品、调库存、查看异常订单 |
|
- 下单后库存和订单状态是否闭环
|
||||||
|
- 失败补偿是否真的能回滚
|
||||||
|
|
||||||
### 范围控制(一定要先做“能交付”的版本)
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
- 只做最小支付模拟,不接真实支付网关
|
|
||||||
- 不做复杂促销(满减、优惠券、拼团)
|
|
||||||
- 不做推荐算法,商品排序先按上架时间或销量
|
|
||||||
- 不做分布式事务框架,先用“本地事务 + 失败补偿”思路
|
|
||||||
- 不做消息中间件集群,第一版可同步调用
|
|
||||||
|
|
||||||
## 2. 架构与时序
|
|
||||||
|
|
||||||
### 请求路由链路
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
actor U as 用户
|
|
||||||
participant FE as 前端
|
|
||||||
participant GW as API Gateway
|
|
||||||
participant AUTH as Auth
|
|
||||||
participant CATALOG as Catalog
|
|
||||||
participant ORDER as Order
|
|
||||||
participant INV as Inventory
|
|
||||||
|
|
||||||
U->>FE: 打开商品页并下单
|
|
||||||
FE->>GW: POST /api/orders
|
|
||||||
GW->>AUTH: 校验 JWT
|
|
||||||
AUTH-->>GW: 用户身份合法
|
|
||||||
GW->>ORDER: 创建订单请求
|
|
||||||
ORDER->>INV: 扣减库存
|
|
||||||
INV-->>ORDER: 扣减结果
|
|
||||||
ORDER-->>GW: 订单创建成功
|
|
||||||
GW-->>FE: 返回订单号和状态
|
|
||||||
```
|
|
||||||
|
|
||||||
### 失败补偿思路(避免“扣了库存却没订单”)
|
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["创建订单请求"] --> B["校验库存是否足够"]
|
prd["PRD"] --> fe["前端页面"]
|
||||||
B -->|不足| C["返回失败"]
|
fe --> gw["API Gateway"]
|
||||||
B -->|充足| D["预扣库存"]
|
gw --> auth["Auth Service"]
|
||||||
D --> E["写入订单记录"]
|
gw --> catalog["Catalog Service"]
|
||||||
E -->|成功| F["确认扣减完成"]
|
gw --> inventory["Inventory Service"]
|
||||||
E -->|失败| G["回滚库存"]
|
gw --> order["Order Service"]
|
||||||
G --> H["记录补偿日志"]
|
order --> inventory
|
||||||
F --> I["返回下单成功"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. 推荐技术栈
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
- **前端**:Next.js + TypeScript + Tailwind CSS + shadcn/ui
|
|
||||||
- **服务端**:Node.js + Express / Fastify
|
|
||||||
- **网关**:Express Gateway 或自建 BFF 网关
|
|
||||||
- **数据库**:PostgreSQL(每个服务独立库或独立 schema)
|
|
||||||
- **缓存(可选)**:Redis(热商品列表、会话短缓存)
|
|
||||||
- **部署**:Docker Compose(本地)+ Zeabur / Railway(云端)
|
|
||||||
|
|
||||||
## 4. 分步实现路径(可直接照做)
|
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
|
||||||
<ClientOnly>
|
|
||||||
<StepBar :active="1" :items="[
|
|
||||||
{ title: '定边界', description: '先明确服务拆分和业务范围' },
|
|
||||||
{ title: '搭基础', description: '网关、鉴权、数据库连接先跑通' },
|
|
||||||
{ title: '接业务', description: '商品、订单、库存链路打通' },
|
|
||||||
{ title: '交付上线', description: '部署、文档、演示材料补齐' }
|
|
||||||
]" />
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### 第一步:起项目骨架与网关
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我搭建一个买菜微服务项目骨架。
|
请基于当前 PRD,帮我生成一个生鲜电商微服务系统的项目骨架。
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
1. 创建 api-gateway、auth-service、catalog-service、inventory-service、order-service 五个服务目录
|
1. 生成前端用户端和管理端骨架
|
||||||
2. 每个服务都包含最小可运行的 Express 入口
|
2. 生成 api-gateway、auth-service、catalog-service、inventory-service、order-service 五个目录
|
||||||
3. gateway 支持把 /api/catalog/* 转发到 catalog-service,把 /api/orders/* 转发到 order-service
|
3. 每个服务先只做最小可运行入口
|
||||||
4. 使用 TypeScript
|
4. 先不接真实数据库和支付
|
||||||
5. 给出本地启动脚本(可用 pnpm workspace 或 npm workspaces)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第二步:先做鉴权,再做业务接口
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
先完成:
|
| 检查项 | 要看什么 |
|
||||||
|
|------|------|
|
||||||
|
| 页面是否对 | 页面数量、入口、功能是否符合 PRD |
|
||||||
|
| 接口是否对 | catalog、inventory、orders 是否闭环 |
|
||||||
|
| 权限是否对 | 用户与管理员权限是否隔离 |
|
||||||
|
| 数据是否对 | 商品、库存、订单状态是否一致 |
|
||||||
|
| 演示是否对 | 是否能演示“浏览 -> 下单 -> 查单 -> 管理库存” |
|
||||||
|
|
||||||
- 用户注册 / 登录
|
## 最后的预期效果
|
||||||
- JWT 发放和校验中间件
|
|
||||||
- 网关统一鉴权(白名单接口可放行)
|
|
||||||
|
|
||||||
```text
|
- 一套可运行的生鲜电商微服务系统
|
||||||
请帮我实现 auth-service 的最小鉴权链路。
|
- 一份同级 PRD 文档
|
||||||
|
- 用户端、管理端、网关和 4 个核心服务
|
||||||
|
- JWT 鉴权、库存扣减、订单管理
|
||||||
|
- README 和演示方案
|
||||||
|
|
||||||
目标:
|
## 验收标准
|
||||||
1. POST /register
|
|
||||||
2. POST /login
|
|
||||||
3. 输出 access token
|
|
||||||
4. gateway 中间件可以验证 token 并把 userId、role 注入请求上下文
|
|
||||||
5. 提供一个受保护示例接口用于测试
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第三步:商品与库存服务
|
| 维度 | 最低达标 |
|
||||||
|
|------|------|
|
||||||
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
|
| 产品闭环 | 浏览、下单、库存、查单可以跑通 |
|
||||||
|
| 后台能力 | 商品、库存、订单管理可以查看 |
|
||||||
|
| 工程完整度 | 前端、网关、服务、数据库链路已接通 |
|
||||||
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
优先做这几个接口:
|
::: tip 🚀 完成后你会得到什么?
|
||||||
|
你得到的不只是一个电商练习题,而是一套微服务项目的开发样例。后面再做复杂后端系统时,这会非常有用。
|
||||||
- `GET /api/catalog/products`
|
|
||||||
- `GET /api/catalog/products/:id`
|
|
||||||
- `PATCH /api/inventory/:productId`(管理员)
|
|
||||||
|
|
||||||
### 第四步:订单服务打通主链路
|
|
||||||
|
|
||||||
优先做下单和查单:
|
|
||||||
|
|
||||||
- `POST /api/orders`
|
|
||||||
- `GET /api/orders/:id`
|
|
||||||
- `GET /api/orders/my`
|
|
||||||
|
|
||||||
下单流程必须至少包含:
|
|
||||||
|
|
||||||
1. 鉴权通过
|
|
||||||
2. 校验商品和库存
|
|
||||||
3. 创建订单
|
|
||||||
4. 扣减库存
|
|
||||||
5. 失败时回滚或补偿
|
|
||||||
|
|
||||||
### 第五步:管理端最小闭环
|
|
||||||
|
|
||||||
管理员界面先做三块就够:
|
|
||||||
|
|
||||||
- 商品列表 + 上下架按钮
|
|
||||||
- 库存调整表单
|
|
||||||
- 订单列表(含状态筛选)
|
|
||||||
|
|
||||||
### 第六步:部署与文档
|
|
||||||
|
|
||||||
至少完成:
|
|
||||||
|
|
||||||
- 一份项目结构图
|
|
||||||
- 一份服务启动说明
|
|
||||||
- 一份关键接口说明
|
|
||||||
- 一份本地联调步骤
|
|
||||||
|
|
||||||
## 5. 交付物要求
|
|
||||||
|
|
||||||
你至少要提交这些内容:
|
|
||||||
|
|
||||||
- 可运行项目代码(网关 + 4 个服务 + 前端)
|
|
||||||
- 演示地址或本地可复现说明
|
|
||||||
- README(含架构图、启动方式、接口概览)
|
|
||||||
- 60 秒到 120 秒演示视频
|
|
||||||
- 关键页面截图(用户下单、管理员改库存、订单详情)
|
|
||||||
|
|
||||||
## 6. 验收标准
|
|
||||||
|
|
||||||
| 维度 | 最低达标 | 加分项 |
|
|
||||||
|------|------|------|
|
|
||||||
| 架构清晰度 | 服务边界明确,网关可用 | 有统一错误码和服务间追踪日志 |
|
|
||||||
| 业务闭环 | 浏览商品 -> 下单 -> 查单跑通 | 有库存不足、下单失败等异常处理 |
|
|
||||||
| 权限控制 | 用户与管理员权限隔离 | 服务端接口也有角色校验,不只前端隐藏 |
|
|
||||||
| 工程质量 | 项目可启动、接口可调试 | 有 Docker Compose、一键启动脚本 |
|
|
||||||
| 交付完整度 | README、截图、演示视频齐全 | 有性能优化或缓存策略说明 |
|
|
||||||
|
|
||||||
## 7. 提交前最后检查
|
|
||||||
|
|
||||||
<el-card shadow="hover" style="margin: 20px 0; border-radius: 12px;">
|
|
||||||
<template #header>
|
|
||||||
<div style="font-weight: bold; font-size: 16px;">提交前最后看一眼</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<ul style="list-style-type: none; padding-left: 0;">
|
|
||||||
<li><label><input type="checkbox" disabled /> 网关已接入鉴权并能正确转发请求</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 商品、库存、订单三个核心服务已打通</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 下单失败时有清晰错误提示和补偿处理</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 用户端和管理端都可完成核心操作</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> README、架构图、演示视频已准备完整</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 项目已部署或有完整本地复现步骤</label></li>
|
|
||||||
</ul>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
这个作业最重要的不是“服务越多越好”,而是你能不能把边界、协作和失败处理讲清楚并做扎实。
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
@@ -0,0 +1,361 @@
|
|||||||
|
# PRD:Go 交通数据分析与可视化平台
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:先明确数据产品的口径、模块和接口,再进入实现。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个“数据接入 + 聚合分析 + 看板展示”的完整型项目。重点是把原始交通数据转换成可读的分析结果和告警。
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个支持事件接入、窗口聚合、异常检测和大屏展示的 Go 数据分析平台。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
SOURCE["数据源 / 模拟器"] --> API["Go API"]
|
||||||
|
API --> RAW["原始数据表"]
|
||||||
|
RAW --> AGG["聚合任务"]
|
||||||
|
AGG --> ALERT["告警规则"]
|
||||||
|
AGG --> DASH["Dashboard API"]
|
||||||
|
ALERT --> DASH
|
||||||
|
ADMIN["admin.xxx.com<br/>管理后台"] --> DASH
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.0 技术选型建议
|
||||||
|
|
||||||
|
- 后端框架:`Go + Gin/Fiber`
|
||||||
|
- 数据库:`PostgreSQL`
|
||||||
|
- 聚合任务:`robfig/cron`
|
||||||
|
- 前端:`React / Next.js`
|
||||||
|
- 图表:`ECharts` 或 `AntV`
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 分析看板:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.1 竞品参考(官方)
|
||||||
|
|
||||||
|
- [TomTom Traffic Index](https://www.tomtom.com/traffic-index/)
|
||||||
|
|
||||||
|
## 1.2 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考真实交通分析产品:
|
||||||
|
|
||||||
|
- 借鉴 `TomTom Traffic Index` 的指标表达方式:趋势、拥堵程度、城市/路口排行应直观可读
|
||||||
|
- 看板首页应优先展示关键指标和异常信息,而不是堆很多图
|
||||||
|
- 趋势页、排行页、告警页要有清晰的分工
|
||||||
|
- 管理端应强调数据导入、任务状态和告警处理,而不是只看静态图表
|
||||||
|
- 整体设计要更像数据产品和运营看板,而不是普通后台列表
|
||||||
|
|
||||||
|
## 1.3 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `TomTom Traffic Index` 的总览页
|
||||||
|
- 重点看:如何用少量关键指标快速建立全局认知
|
||||||
|
- `TomTom Traffic Index` 的趋势和排名表达
|
||||||
|
- 重点看:图表和排行如何帮助用户快速理解问题
|
||||||
|
- 数据产品常见监控页
|
||||||
|
- 重点看:告警、数据状态和任务状态如何分区展示
|
||||||
|
|
||||||
|
因此本项目建议:
|
||||||
|
|
||||||
|
- 总览页强调关键指标
|
||||||
|
- 趋势页强调时间变化
|
||||||
|
- 告警页强调异常定位
|
||||||
|
- 管理端强调数据导入和任务健康状态
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 关注交通趋势和拥堵状态的分析人员
|
||||||
|
- 查看异常告警与处理结果的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 原始数据可稳定接入
|
||||||
|
- 聚合指标可查询
|
||||||
|
- 告警可见、可处理
|
||||||
|
- 可视化页面可支撑汇报和演示
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 数据接入接口
|
||||||
|
- 原始数据落库
|
||||||
|
- 定时聚合任务
|
||||||
|
- 异常检测规则
|
||||||
|
- 趋势图、Top 路口、告警面板
|
||||||
|
- 管理端数据导入或模拟数据入口
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- Kafka/Flink 级流处理
|
||||||
|
- 复杂 GIS 地图引擎
|
||||||
|
- 机器学习预测模型
|
||||||
|
- 多租户平台权限
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 分析用户 | 查看看板、趋势、排行榜 |
|
||||||
|
| 管理员 | 导入数据、处理告警、查看任务状态 |
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
## 5.1 页面架构总览
|
||||||
|
|
||||||
|
当前 PRD 定义为 `2 套入口,6 个大页面`:
|
||||||
|
|
||||||
|
- 用户看板 `4` 个大页面
|
||||||
|
- 后台管理台 `2` 个大页面
|
||||||
|
|
||||||
|
### A. 分析看板 `app.xxx.com`
|
||||||
|
|
||||||
|
#### 1. 总览页 `app:/dashboard`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 总车流
|
||||||
|
- 当前告警数
|
||||||
|
- 最拥堵路口
|
||||||
|
|
||||||
|
#### 2. 趋势页 `app:/dashboard/trend`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 车流趋势图
|
||||||
|
- 时间范围切换
|
||||||
|
|
||||||
|
#### 3. 路口排行页 `app:/dashboard/intersections`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 拥堵排行
|
||||||
|
- 关键路口指标
|
||||||
|
|
||||||
|
#### 4. 告警页 `app:/alerts`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看告警
|
||||||
|
- 筛选级别
|
||||||
|
- 标记处理状态
|
||||||
|
|
||||||
|
### B. 后台管理台 `admin.xxx.com`
|
||||||
|
|
||||||
|
#### 5. 数据导入页 `admin:/imports`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 导入 CSV
|
||||||
|
- 查看导入任务状态
|
||||||
|
|
||||||
|
#### 6. 任务与告警管理页 `admin:/operations`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看聚合任务状态
|
||||||
|
- 查看告警处理记录
|
||||||
|
|
||||||
|
## 5.2 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
source["数据源"] --> ingest["接入接口"]
|
||||||
|
ingest --> raw["原始数据表"]
|
||||||
|
raw --> agg["聚合任务"]
|
||||||
|
agg --> trend["趋势页"]
|
||||||
|
agg --> rank["排行页"]
|
||||||
|
agg --> alerts["告警页"]
|
||||||
|
admin["管理员"] --> imports["数据导入页"]
|
||||||
|
imports --> ingest
|
||||||
|
admin --> ops["任务与告警管理页"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 数据事件:接收成功 / 校验失败
|
||||||
|
- 聚合任务:待执行 -> 执行中 -> 成功 / 失败
|
||||||
|
- 告警:新建 -> 已确认 -> 已处理
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- React / Next.js
|
||||||
|
- ECharts / AntV
|
||||||
|
- TypeScript
|
||||||
|
|
||||||
|
建议页面:
|
||||||
|
|
||||||
|
| 页面 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 总览看板 | `/dashboard` | 今日流量、拥堵指数、告警数 |
|
||||||
|
| 趋势页 | `/dashboard/trend` | 分时趋势图 |
|
||||||
|
| 路口分析页 | `/dashboard/intersections` | Top 路口排行 |
|
||||||
|
| 告警页 | `/alerts` | 告警列表与处理状态 |
|
||||||
|
| 数据管理页 | `/admin/imports` | 导入数据、查看任务日志 |
|
||||||
|
|
||||||
|
前端关键组件:
|
||||||
|
|
||||||
|
- 指标卡片
|
||||||
|
- 折线图/柱状图
|
||||||
|
- 排行榜表格
|
||||||
|
- 告警列表
|
||||||
|
- 时间范围筛选器
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Go
|
||||||
|
- Gin 或 Fiber
|
||||||
|
- PostgreSQL
|
||||||
|
- robfig/cron
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `ingest`
|
||||||
|
- `aggregation`
|
||||||
|
- `alerts`
|
||||||
|
- `dashboard`
|
||||||
|
- `imports`
|
||||||
|
- `admin`
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
raw_traffic_events (
|
||||||
|
id bigserial primary key,
|
||||||
|
intersection_id text,
|
||||||
|
event_time timestamptz,
|
||||||
|
vehicle_count int,
|
||||||
|
avg_speed numeric,
|
||||||
|
source text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
traffic_agg_1m (
|
||||||
|
id bigserial primary key,
|
||||||
|
intersection_id text,
|
||||||
|
window_start timestamptz,
|
||||||
|
total_vehicles int,
|
||||||
|
avg_speed numeric,
|
||||||
|
congestion_index numeric
|
||||||
|
)
|
||||||
|
|
||||||
|
traffic_agg_5m (
|
||||||
|
id bigserial primary key,
|
||||||
|
intersection_id text,
|
||||||
|
window_start timestamptz,
|
||||||
|
total_vehicles int,
|
||||||
|
avg_speed numeric,
|
||||||
|
congestion_index numeric
|
||||||
|
)
|
||||||
|
|
||||||
|
alerts (
|
||||||
|
id bigserial primary key,
|
||||||
|
intersection_id text,
|
||||||
|
level text,
|
||||||
|
rule_code text,
|
||||||
|
status text,
|
||||||
|
message text,
|
||||||
|
created_at timestamptz,
|
||||||
|
resolved_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
import_jobs (
|
||||||
|
id bigserial primary key,
|
||||||
|
filename text,
|
||||||
|
status text,
|
||||||
|
total_rows int,
|
||||||
|
success_rows int,
|
||||||
|
failed_rows int,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 接入事件总数
|
||||||
|
- 聚合任务成功率
|
||||||
|
- 告警总数与处理率
|
||||||
|
- 热点路口排行
|
||||||
|
- 导入任务成功率
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- 接入接口错误率
|
||||||
|
- 聚合任务耗时
|
||||||
|
- 数据库写入失败率
|
||||||
|
- 看板查询接口耗时
|
||||||
|
|
||||||
|
## 7. 指标与规则
|
||||||
|
|
||||||
|
第一版指标:
|
||||||
|
|
||||||
|
- 每分钟车流量
|
||||||
|
- 每 5 分钟聚合车流量
|
||||||
|
- 平均车速
|
||||||
|
- 拥堵指数
|
||||||
|
- Top10 拥堵路口
|
||||||
|
|
||||||
|
第一版告警规则:
|
||||||
|
|
||||||
|
- 当前流量高于近 5 分钟均值阈值
|
||||||
|
- 当前速度连续低于阈值
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/traffic/events` | 写入单条交通事件 |
|
||||||
|
| `POST` | `/api/traffic/import` | 上传 CSV 或批量导入 |
|
||||||
|
| `GET` | `/api/dashboard/overview` | 获取概览卡片数据 |
|
||||||
|
| `GET` | `/api/dashboard/trend` | 获取趋势图数据 |
|
||||||
|
| `GET` | `/api/dashboard/intersections/top` | 获取拥堵路口排行 |
|
||||||
|
| `GET` | `/api/alerts` | 获取告警列表 |
|
||||||
|
| `PATCH` | `/api/alerts/:id/resolve` | 处理告警 |
|
||||||
|
| `GET` | `/api/admin/import-jobs` | 获取导入任务状态 |
|
||||||
|
|
||||||
|
`POST /api/traffic/events` 请求示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"intersectionId": "A-101",
|
||||||
|
"timestamp": "2026-04-01T08:30:00+08:00",
|
||||||
|
"vehicleCount": 42,
|
||||||
|
"avgSpeed": 18.6,
|
||||||
|
"source": "simulator"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. 非功能要求
|
||||||
|
|
||||||
|
- 聚合任务可重复执行且结果稳定
|
||||||
|
- API 返回结构统一
|
||||||
|
- 导入失败要能定位原因
|
||||||
|
- 看板查询响应时间可接受
|
||||||
|
|
||||||
|
## 10. 开发顺序建议
|
||||||
|
|
||||||
|
1. Go API 骨架与数据表
|
||||||
|
2. 事件接入接口
|
||||||
|
3. 聚合任务
|
||||||
|
4. 告警规则
|
||||||
|
5. Dashboard 查询接口
|
||||||
|
6. 前端图表页
|
||||||
|
|
||||||
|
## 11. 待确认项
|
||||||
|
|
||||||
|
- 是否提供 CSV 导入作为主要演示入口
|
||||||
|
- 是否需要地图视图
|
||||||
|
- 告警阈值是否写死还是后台可配
|
||||||
|
- 前端图表库选 ECharts 还是 AntV
|
||||||
@@ -1,239 +1,120 @@
|
|||||||
# 交通大数据可视化分析 (Go项目)
|
# Go 交通数据分析平台开发实战
|
||||||
|
|
||||||
很多同学学 Go 时会卡在一个问题:会写接口,但不知道怎么把“数据处理能力”和“业务展示能力”组合成一个完整项目。
|
这个项目不是“写几个 Go 接口”,而是围绕一份真实 PRD,把一个数据接入、聚合、告警、可视化的产品原型推进出来。
|
||||||
|
|
||||||
这个大作业就是为了解这个问题。你会做一个可运行的交通数据平台,从数据接入、清洗、聚合,到可视化展示和告警,一条链路走完。
|
你会同时看到三件事:
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
- 项目要做成什么
|
||||||
打造一个 **交通大数据可视化分析平台(Go 后端)**。系统可以接收交通流量数据,完成时间窗口聚合与异常检测,并在可视化页面展示趋势、拥堵热力、路口排名和告警记录。
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
|
::: tip PRD 入口
|
||||||
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定场景', description: '先明确数据来源、指标口径和展示目标' },
|
{ title: '看 PRD', description: '先明确数据来源、指标、告警规则和看板范围' },
|
||||||
{ title: '搭管道', description: '接入、清洗、存储、聚合链路先跑通' },
|
{ title: '生成骨架', description: '让 AI 先产出 API、聚合任务和看板页骨架' },
|
||||||
{ title: '做分析', description: '完成趋势图、热力图和异常告警' },
|
{ title: '监工迭代', description: '逐模块验收、补接口、修指标口径和告警链路' },
|
||||||
{ title: '交付上线', description: '部署、文档、演示材料补齐' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的数据产品原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个项目值得做?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
这个题目同时练了三种在真实项目里非常关键的能力:
|
这是一个 Go 交通数据分析平台:
|
||||||
|
|
||||||
- **工程能力**:Go 接口设计、并发处理、任务调度
|
- 接收原始交通事件
|
||||||
- **数据能力**:时间序列聚合、指标建模、异常检测
|
- 做窗口聚合
|
||||||
- **产品能力**:把分析结果变成可读、可操作的可视化页面
|
- 计算趋势和拥堵指标
|
||||||
|
- 生成告警
|
||||||
|
- 在前端看板中展示结果
|
||||||
|
|
||||||
做完后,你不只是“写了个后端”,而是能说清一个数据产品如何从输入走到决策。
|
## 开发过程怎么走?
|
||||||
|
|
||||||
## 1. 项目全景与范围控制
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
### 系统模块图
|
先确认:
|
||||||
|
|
||||||
```mermaid
|
- 数据来源和字段是否拍板
|
||||||
flowchart LR
|
- 指标口径是否清楚
|
||||||
source["数据源<br/>路口设备 / CSV / 模拟器"] --> ingest["Go Ingest API"]
|
- 告警规则是否先收敛到简单版本
|
||||||
ingest --> clean["数据清洗与标准化"]
|
- 看板页面范围是否合理
|
||||||
clean --> rawdb["原始数据表"]
|
|
||||||
clean --> agg["聚合任务(1m/5m/1h)"]
|
|
||||||
agg --> aggdb["聚合结果表"]
|
|
||||||
agg --> detect["异常检测任务"]
|
|
||||||
detect --> alertdb["告警表"]
|
|
||||||
aggdb --> dashboard["可视化看板"]
|
|
||||||
alertdb --> dashboard
|
|
||||||
```
|
|
||||||
|
|
||||||
### 建议分析维度
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
第一版只聚焦这些核心指标:
|
第一轮先生成:
|
||||||
|
|
||||||
- 时间窗口车流量(每分钟 / 每 5 分钟 / 每小时)
|
- Go API 服务骨架
|
||||||
- 路口拥堵指数(可用速度反比或排队长度估算)
|
- 数据接入接口
|
||||||
- TOP 拥堵路口排名
|
- 聚合任务骨架
|
||||||
- 异常突增告警(同比前 5 分钟或滑动均值)
|
- 总览看板、趋势页、告警页
|
||||||
|
|
||||||
### 范围控制(防止项目失控)
|
### 3. 再进入“监工模式”
|
||||||
|
|
||||||
- 第一版不做实时流处理平台(如 Kafka/Flink 集群)
|
你要重点盯这几件事:
|
||||||
- 第一版不做复杂地图引擎,热力可先用网格或散点替代
|
|
||||||
- 第一版不做机器学习预测,先用规则阈值异常检测
|
|
||||||
- 第一版不做多租户权限系统,只保留普通用户 + 管理员
|
|
||||||
|
|
||||||
## 2. 数据链路与时序
|
- 原始数据是否正确入库
|
||||||
|
- 聚合口径是否一致
|
||||||
|
- 告警规则是否符合预期
|
||||||
|
- 看板展示和后端数据是否一致
|
||||||
|
- API 是否有统一返回结构和错误处理
|
||||||
|
|
||||||
### 数据从接入到看板的主流程
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
participant Device as 数据源
|
|
||||||
participant API as Go API
|
|
||||||
participant DB as PostgreSQL
|
|
||||||
participant Job as 聚合任务
|
|
||||||
participant FE as Dashboard
|
|
||||||
|
|
||||||
Device->>API: POST /api/traffic/events
|
|
||||||
API->>API: 参数校验与标准化
|
|
||||||
API->>DB: 写入 raw_traffic_events
|
|
||||||
Job->>DB: 定时读取原始数据
|
|
||||||
Job->>DB: 写入 traffic_agg_1m / traffic_agg_5m
|
|
||||||
Job->>DB: 写入 alerts
|
|
||||||
FE->>API: GET /api/dashboard/overview
|
|
||||||
API->>DB: 查询聚合结果与告警
|
|
||||||
API-->>FE: 返回图表数据
|
|
||||||
```
|
|
||||||
|
|
||||||
### 异常检测逻辑(简版)
|
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["读取最近 10 分钟聚合值"] --> B["计算近 5 分钟均值"]
|
prd["PRD"] --> ingest["数据接入 API"]
|
||||||
B --> C["当前值 > 均值 * 阈值?"]
|
ingest --> raw["原始数据表"]
|
||||||
C -->|否| D["正常,无告警"]
|
raw --> agg["聚合任务"]
|
||||||
C -->|是| E["生成告警记录"]
|
agg --> alert["告警规则"]
|
||||||
E --> F["标记级别(低/中/高)"]
|
agg --> dashboard["看板接口"]
|
||||||
F --> G["写入 alerts 表"]
|
alert --> dashboard
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. 推荐技术栈
|
## 怎么让 AI 帮你生成?
|
||||||
|
|
||||||
- **后端**:Go + Gin / Fiber
|
|
||||||
- **数据处理**:Go `cron` / `robfig/cron`(定时聚合)
|
|
||||||
- **数据库**:PostgreSQL(可选 TimescaleDB)
|
|
||||||
- **缓存(可选)**:Redis(热点看板数据)
|
|
||||||
- **前端**:React / Next.js + ECharts / AntV
|
|
||||||
- **部署**:Docker Compose + Zeabur / Railway / 自托管
|
|
||||||
|
|
||||||
## 4. 分步实现路径
|
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
|
||||||
<ClientOnly>
|
|
||||||
<StepBar :active="1" :items="[
|
|
||||||
{ title: '定场景', description: '先明确数据来源、指标口径和展示目标' },
|
|
||||||
{ title: '搭管道', description: '接入、清洗、存储、聚合链路先跑通' },
|
|
||||||
{ title: '做分析', description: '完成趋势图、热力图和异常告警' },
|
|
||||||
{ title: '交付上线', description: '部署、文档、演示材料补齐' }
|
|
||||||
]" />
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### 第一步:搭 Go 项目骨架和数据模型
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请帮我创建一个 Go 交通数据分析项目骨架。
|
请基于当前 PRD,帮我生成一个 Go 交通数据分析平台骨架。
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
1. 使用 Gin(或 Fiber)创建 API 服务
|
1. 使用 Gin 或 Fiber
|
||||||
2. 按 handler / service / repository / model 分层
|
2. 提供数据接入接口
|
||||||
3. 设计并创建数据表:
|
3. 提供聚合任务骨架
|
||||||
- raw_traffic_events
|
4. 提供 dashboard 和 alerts 接口骨架
|
||||||
- traffic_agg_1m
|
5. 先不做真实复杂分析,只做可运行结构
|
||||||
- traffic_agg_5m
|
|
||||||
- alerts
|
|
||||||
4. 提供一个健康检查接口 /health
|
|
||||||
5. 给出本地启动步骤(含数据库连接配置)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第二步:完成数据接入接口
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
先做事件写入:
|
| 检查项 | 要看什么 |
|
||||||
|
|
||||||
- `POST /api/traffic/events`
|
|
||||||
- 字段至少包含:`intersection_id`、`timestamp`、`vehicle_count`、`avg_speed`
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我实现 POST /api/traffic/events。
|
|
||||||
|
|
||||||
要求:
|
|
||||||
1. 做参数校验(空值、类型、时间格式)
|
|
||||||
2. 标准化 timestamp 到统一时区
|
|
||||||
3. 写入 raw_traffic_events
|
|
||||||
4. 返回统一 JSON 结构(code、message、data)
|
|
||||||
5. 提供一组可直接用于调试的 curl 示例
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第三步:实现聚合任务
|
|
||||||
|
|
||||||
至少完成:
|
|
||||||
|
|
||||||
- 1 分钟窗口聚合
|
|
||||||
- 5 分钟窗口聚合
|
|
||||||
- 聚合结果接口 `GET /api/dashboard/trend`
|
|
||||||
|
|
||||||
### 第四步:实现告警规则
|
|
||||||
|
|
||||||
建议第一版规则:
|
|
||||||
|
|
||||||
- 当前流量 `> 近 5 分钟均值 * 1.8` 触发中级告警
|
|
||||||
- 当前平均速度 `< 阈值` 且持续 3 个窗口,触发高级拥堵告警
|
|
||||||
|
|
||||||
### 第五步:完成可视化页面
|
|
||||||
|
|
||||||
建议页面模块:
|
|
||||||
|
|
||||||
- 总览卡片:今日总车流、当前告警数、最拥堵路口
|
|
||||||
- 趋势图:近 24 小时车流曲线
|
|
||||||
- 路口排行:拥堵指数 TOP10
|
|
||||||
- 告警面板:实时/历史告警列表
|
|
||||||
|
|
||||||
### 第六步:补齐部署与文档
|
|
||||||
|
|
||||||
至少包含:
|
|
||||||
|
|
||||||
- 数据口径说明(每个指标如何计算)
|
|
||||||
- 接口文档(输入/输出示例)
|
|
||||||
- 本地与线上部署步骤
|
|
||||||
- 示例数据导入方法
|
|
||||||
|
|
||||||
## 5. 可直接使用的接口清单(最小可用)
|
|
||||||
|
|
||||||
| 模块 | 接口 |
|
|
||||||
|------|------|
|
|------|------|
|
||||||
| 数据接入 | `POST /api/traffic/events` |
|
| 接口是否对 | ingest、dashboard、alerts 是否闭环 |
|
||||||
| 总览数据 | `GET /api/dashboard/overview` |
|
| 数据是否对 | 原始表、聚合表、告警表是否一致 |
|
||||||
| 趋势数据 | `GET /api/dashboard/trend?range=24h` |
|
| 指标是否对 | 趋势、排名、告警口径是否合理 |
|
||||||
| 热点路口 | `GET /api/dashboard/intersections/top` |
|
| 页面是否对 | 看板展示和后端结果是否对齐 |
|
||||||
| 告警列表 | `GET /api/alerts?level=high&status=open` |
|
| 演示是否对 | 是否能演示“接入 -> 聚合 -> 告警 -> 展示” |
|
||||||
| 告警处理 | `PATCH /api/alerts/:id/resolve` |
|
|
||||||
|
|
||||||
## 6. 交付物要求
|
## 最后的预期效果
|
||||||
|
|
||||||
- 可运行项目代码(Go API + 可视化前端)
|
- 一套可运行的 Go 数据分析平台
|
||||||
- 数据库表结构与初始化脚本
|
- 一份同级 PRD 文档
|
||||||
- README(架构图、运行说明、指标解释)
|
- 数据接入、聚合、告警、看板展示
|
||||||
- 关键页面截图(趋势图、排名、告警)
|
- README 和演示方案
|
||||||
- 60 秒到 120 秒演示视频
|
|
||||||
|
|
||||||
## 7. 验收标准
|
## 验收标准
|
||||||
|
|
||||||
| 维度 | 最低达标 | 加分项 |
|
| 维度 | 最低达标 |
|
||||||
|------|------|------|
|
|------|------|
|
||||||
| 数据链路 | 接入、存储、聚合、展示完整跑通 | 支持重放历史数据和批量导入 |
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
| 分析能力 | 有趋势、排名、告警三个核心模块 | 告警支持分级与处理状态流转 |
|
| 产品闭环 | 接入、聚合、告警、看板可以跑通 |
|
||||||
| Go 工程质量 | 代码分层清晰,错误处理明确 | 有结构化日志与基础性能优化 |
|
| 分析能力 | 趋势、排行、告警三个核心模块可用 |
|
||||||
| 可视化质量 | 关键图表可读,指标口径一致 | 增加地图层或交互筛选能力 |
|
| 工程完整度 | Go API、数据库、前端看板链路已接通 |
|
||||||
| 交付完整度 | README、截图、演示视频齐全 | 有线上演示地址和压测说明 |
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
## 8. 提交前最后检查
|
::: tip 🚀 完成后你会得到什么?
|
||||||
|
你得到的不只是一个接口项目,而是一套“数据接入 + 数据产品”型项目的开发样例。
|
||||||
<el-card shadow="hover" style="margin: 20px 0; border-radius: 12px;">
|
|
||||||
<template #header>
|
|
||||||
<div style="font-weight: bold; font-size: 16px;">提交前最后看一眼</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<ul style="list-style-type: none; padding-left: 0;">
|
|
||||||
<li><label><input type="checkbox" disabled /> 数据接入接口可稳定写入原始事件</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 聚合任务能按窗口产出统计结果</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 告警规则生效并可在页面查看</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 看板页面可展示趋势、排名和告警</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> README 已写清口径、接口和运行步骤</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 项目已部署或可完整本地复现</label></li>
|
|
||||||
</ul>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
这个作业的关键,不是图表多炫,而是你能不能保证“口径一致、链路闭环、告警可信”。
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
@@ -0,0 +1,405 @@
|
|||||||
|
# PRD:智能旅游规划 Agent 编排平台
|
||||||
|
|
||||||
|
状态:Draft v0.1
|
||||||
|
目标:先确认这个 Agent 产品的最小可用范围,再进入开发。
|
||||||
|
|
||||||
|
## 1. 项目定位
|
||||||
|
|
||||||
|
这是一个面向真实旅行规划场景的 AI 产品,不只是聊天,而是把结构化输入转成可执行行程。
|
||||||
|
|
||||||
|
一句话定义:
|
||||||
|
做一个可以生成、保存、调整与导出旅行计划的 Agent 编排平台。
|
||||||
|
|
||||||
|
系统总览:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
WWW["www.xxx.com<br/>官网前台"] --> API["应用 API / 管理 API"]
|
||||||
|
APP["app.xxx.com<br/>用户工作台"] --> API
|
||||||
|
ADMIN["admin.xxx.com<br/>后台管理台"] --> API
|
||||||
|
API --> AUTH["Supabase Auth"]
|
||||||
|
API --> DB["Supabase Postgres"]
|
||||||
|
API --> MODEL["LLM / Agent 编排层"]
|
||||||
|
API --> EXT["天气 / 地图 / POI 外部信息源"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.0 技术选型建议
|
||||||
|
|
||||||
|
- 前端框架:`Next.js App Router`
|
||||||
|
- 用户鉴权:`Supabase Auth`
|
||||||
|
- 数据库:`Supabase Postgres`
|
||||||
|
- 模型层:统一后端服务调用大模型
|
||||||
|
- 可选缓存:`Redis`
|
||||||
|
|
||||||
|
站点入口约定:
|
||||||
|
|
||||||
|
- 官网前台:`www.xxx.com`
|
||||||
|
- 用户工作台:`app.xxx.com`
|
||||||
|
- 后台管理台:`admin.xxx.com`
|
||||||
|
|
||||||
|
## 1.1 竞品参考(官方)
|
||||||
|
|
||||||
|
- [Wanderlog](https://wanderlog.com/)
|
||||||
|
|
||||||
|
## 1.2 产品借鉴点
|
||||||
|
|
||||||
|
本项目的产品设计建议参考真实旅行规划产品的做法:
|
||||||
|
|
||||||
|
- 借鉴 `Wanderlog` 的路线规划表达方式:输入后直接看到可编辑的每日行程,而不是只返回一大段文本
|
||||||
|
- 行程详情应突出日期、地点、预算、移动顺序和注意事项
|
||||||
|
- 历史记录页应像“我的行程库”,支持再次打开和二次生成
|
||||||
|
- 后台页应强调热门目的地、失败任务和用户反馈,而不是只看系统日志
|
||||||
|
- 整体设计要体现“行程产品”感,而不是“聊天回答”感
|
||||||
|
|
||||||
|
## 1.3 竞品页面拆解
|
||||||
|
|
||||||
|
建议重点参考的竞品页面结构:
|
||||||
|
|
||||||
|
- `Wanderlog` 首页
|
||||||
|
- 重点看:如何同时讲清楚 itinerary、map、budget、collaboration 这些核心价值
|
||||||
|
- `Wanderlog` 行程页
|
||||||
|
- 重点看:一天一天的安排、地图与列表并存、预算与预订信息并列
|
||||||
|
- `Wanderlog` Pro 页面
|
||||||
|
- 重点看:如何把高级功能做成清晰权益,而不是一长串技术描述
|
||||||
|
|
||||||
|
因此本项目建议:
|
||||||
|
|
||||||
|
- 规划页更像“行程编辑台”
|
||||||
|
- 详情页更像“可执行 itinerary”
|
||||||
|
- 历史页更像“我的旅行库”
|
||||||
|
- 后台页更像“运营与任务中心”
|
||||||
|
|
||||||
|
## 2. 目标用户与核心目标
|
||||||
|
|
||||||
|
目标用户:
|
||||||
|
|
||||||
|
- 想快速获得 3 到 7 天行程安排的普通用户
|
||||||
|
- 需要预算与节奏建议的自由行用户
|
||||||
|
- 维护平台质量和任务健康状态的管理员
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
|
||||||
|
- 用户能在一次表单提交后得到结构化行程
|
||||||
|
- 用户能保存历史计划并再次编辑/重生成
|
||||||
|
- 平台能记录失败任务和生成质量反馈
|
||||||
|
|
||||||
|
## 3. MVP 范围
|
||||||
|
|
||||||
|
第一版必须包含:
|
||||||
|
|
||||||
|
- 规划表单页
|
||||||
|
- 行程详情页
|
||||||
|
- 历史计划页
|
||||||
|
- 计划保存与重生成
|
||||||
|
- 预算拆分
|
||||||
|
- 导出文本/PDF 占位能力
|
||||||
|
- 后台查看任务与失败日志
|
||||||
|
|
||||||
|
第一版不做:
|
||||||
|
|
||||||
|
- 真正的机票/酒店预订
|
||||||
|
- 多城市复杂路线联排
|
||||||
|
- 实时票价与库存同步
|
||||||
|
- 多人协同编辑
|
||||||
|
- 多语言输出
|
||||||
|
|
||||||
|
## 4. 角色与权限
|
||||||
|
|
||||||
|
| 角色 | 权限 |
|
||||||
|
|------|------|
|
||||||
|
| 普通用户 | 创建计划、查看历史、导出、反馈 |
|
||||||
|
| 管理员 | 查看热门目的地、失败任务、用户反馈 |
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
## 5.1 页面架构总览
|
||||||
|
|
||||||
|
当前 PRD 定义为 `3 套入口,8 个大页面`:
|
||||||
|
|
||||||
|
- 官网前台 `1` 个大页面
|
||||||
|
- 用户工作台 `5` 个大页面
|
||||||
|
- 后台管理台 `2` 个大页面
|
||||||
|
|
||||||
|
### A. 官网前台 `www.xxx.com`
|
||||||
|
|
||||||
|
#### 1. 官网首页 `www:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 产品介绍
|
||||||
|
- 典型使用场景
|
||||||
|
- Demo 行程展示
|
||||||
|
- CTA
|
||||||
|
|
||||||
|
### B. 用户工作台 `app.xxx.com`
|
||||||
|
|
||||||
|
#### 2. 登录页 `app:/login`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 登录
|
||||||
|
- 注册入口
|
||||||
|
|
||||||
|
#### 3. 规划页 `app:/planner`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 输入旅行需求
|
||||||
|
- 选择偏好与预算
|
||||||
|
- 发起规划任务
|
||||||
|
|
||||||
|
#### 4. 行程详情页 `app:/trips/:id`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看每日行程
|
||||||
|
- 查看预算拆分
|
||||||
|
- 再次生成和导出
|
||||||
|
|
||||||
|
#### 5. 历史计划页 `app:/history`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看历史计划
|
||||||
|
- 重新打开
|
||||||
|
- 重新生成
|
||||||
|
|
||||||
|
#### 6. 反馈与导出页 `app:/exports`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 导出计划
|
||||||
|
- 提交反馈
|
||||||
|
|
||||||
|
### C. 后台管理台 `admin.xxx.com`
|
||||||
|
|
||||||
|
#### 7. 后台首页 `admin:/`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 热门目的地
|
||||||
|
- 任务成功率
|
||||||
|
- 失败任务数
|
||||||
|
|
||||||
|
#### 8. 任务与反馈页 `admin:/runs`
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
|
||||||
|
- 查看失败任务
|
||||||
|
- 查看用户反馈
|
||||||
|
- 排查异常计划
|
||||||
|
|
||||||
|
## 5.2 关键用户链路
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
user["用户"] --> login["登录"]
|
||||||
|
login --> planner["规划页"]
|
||||||
|
planner --> submit["提交旅行需求"]
|
||||||
|
submit --> agent["Agent 编排层"]
|
||||||
|
agent --> result["生成结构化行程"]
|
||||||
|
result --> detail["行程详情页"]
|
||||||
|
detail --> history["保存到历史计划"]
|
||||||
|
detail --> export["导出 / 分享"]
|
||||||
|
admin["管理员"] --> runs["任务与反馈页"]
|
||||||
|
runs --> optimize["排查失败任务"]
|
||||||
|
```
|
||||||
|
|
||||||
|
关键状态流:
|
||||||
|
|
||||||
|
- 规划任务:待生成 -> 生成中 -> 成功 / 失败
|
||||||
|
- 行程:草稿 -> 已保存 -> 已导出
|
||||||
|
- 反馈:未处理 -> 已查看 -> 已关闭
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Next.js App Router
|
||||||
|
- TypeScript
|
||||||
|
- Tailwind CSS
|
||||||
|
|
||||||
|
建议页面:
|
||||||
|
|
||||||
|
| 页面 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 首页 | `/` | 产品介绍与创建入口 |
|
||||||
|
| 规划页 | `/planner` | 输入需求并提交 |
|
||||||
|
| 行程详情页 | `/trips/:id` | 查看每日计划、预算和注意事项 |
|
||||||
|
| 历史记录页 | `/history` | 查看历史计划 |
|
||||||
|
| 管理后台 | `/admin` | 查看任务状态和平台统计 |
|
||||||
|
|
||||||
|
前端关键组件:
|
||||||
|
|
||||||
|
- 旅行需求表单
|
||||||
|
- 任务进度状态条
|
||||||
|
- Day by Day 行程卡片
|
||||||
|
- 预算拆分卡片
|
||||||
|
- 历史记录列表
|
||||||
|
- 错误重试与反馈组件
|
||||||
|
|
||||||
|
## 6. 后端实现
|
||||||
|
|
||||||
|
推荐技术栈:
|
||||||
|
|
||||||
|
- Node.js + NestJS/Express
|
||||||
|
- PostgreSQL / Supabase
|
||||||
|
- LLM API
|
||||||
|
- 可选 Redis 做短缓存
|
||||||
|
|
||||||
|
后端模块:
|
||||||
|
|
||||||
|
- `auth`
|
||||||
|
- `trip-plans`
|
||||||
|
- `planner`
|
||||||
|
- `exports`
|
||||||
|
- `admin`
|
||||||
|
- `feedback`
|
||||||
|
|
||||||
|
建议数据表:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
trip_plans (
|
||||||
|
id uuid primary key,
|
||||||
|
user_id uuid,
|
||||||
|
origin text,
|
||||||
|
destination text,
|
||||||
|
start_date date,
|
||||||
|
end_date date,
|
||||||
|
budget numeric,
|
||||||
|
preferences jsonb,
|
||||||
|
pace text,
|
||||||
|
status text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
itinerary_days (
|
||||||
|
id uuid primary key,
|
||||||
|
trip_plan_id uuid,
|
||||||
|
day_index int,
|
||||||
|
title text,
|
||||||
|
summary text,
|
||||||
|
day_budget numeric
|
||||||
|
)
|
||||||
|
|
||||||
|
itinerary_items (
|
||||||
|
id uuid primary key,
|
||||||
|
itinerary_day_id uuid,
|
||||||
|
start_time text,
|
||||||
|
end_time text,
|
||||||
|
place_name text,
|
||||||
|
category text,
|
||||||
|
notes text,
|
||||||
|
estimated_cost numeric
|
||||||
|
)
|
||||||
|
|
||||||
|
planner_runs (
|
||||||
|
id uuid primary key,
|
||||||
|
trip_plan_id uuid,
|
||||||
|
provider text,
|
||||||
|
latency_ms int,
|
||||||
|
status text,
|
||||||
|
error_message text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
|
||||||
|
trip_feedback (
|
||||||
|
id uuid primary key,
|
||||||
|
trip_plan_id uuid,
|
||||||
|
user_id uuid,
|
||||||
|
score int,
|
||||||
|
comment text,
|
||||||
|
created_at timestamptz
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6.1 后台指标与监控
|
||||||
|
|
||||||
|
后台建议至少查看这些指标:
|
||||||
|
|
||||||
|
- 日规划任务数
|
||||||
|
- 规划成功率
|
||||||
|
- 平均生成耗时
|
||||||
|
- 热门目的地排行
|
||||||
|
- 用户反馈评分分布
|
||||||
|
- 导出次数
|
||||||
|
|
||||||
|
基础监控建议:
|
||||||
|
|
||||||
|
- 模型调用成功率
|
||||||
|
- 外部信息源失败率
|
||||||
|
- 任务重试次数
|
||||||
|
- 数据库存取耗时
|
||||||
|
|
||||||
|
## 7. 功能清单
|
||||||
|
|
||||||
|
必须完成:
|
||||||
|
|
||||||
|
- 创建旅行计划
|
||||||
|
- 返回结构化每日行程
|
||||||
|
- 查看历史计划
|
||||||
|
- 重生成计划
|
||||||
|
- 预算拆分
|
||||||
|
- 管理端查看失败任务
|
||||||
|
|
||||||
|
可选增强:
|
||||||
|
|
||||||
|
- 热门目的地榜单
|
||||||
|
- POI 数据二次校验
|
||||||
|
- 导出为分享图
|
||||||
|
|
||||||
|
## 8. 接口草案
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `POST` | `/api/trips/plan` | 创建新的规划任务 |
|
||||||
|
| `GET` | `/api/trips/:id` | 获取计划详情 |
|
||||||
|
| `POST` | `/api/trips/:id/regenerate` | 按原条件重新生成 |
|
||||||
|
| `PATCH` | `/api/trips/:id/preferences` | 更新偏好后重算 |
|
||||||
|
| `GET` | `/api/history` | 获取历史计划列表 |
|
||||||
|
| `POST` | `/api/trips/:id/export` | 导出行程 |
|
||||||
|
| `POST` | `/api/trips/:id/feedback` | 提交用户反馈 |
|
||||||
|
| `GET` | `/api/admin/planner-runs` | 获取生成日志 |
|
||||||
|
|
||||||
|
`POST /api/trips/plan` 请求示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"origin": "上海",
|
||||||
|
"destination": "成都",
|
||||||
|
"startDate": "2026-05-01",
|
||||||
|
"endDate": "2026-05-04",
|
||||||
|
"budget": 3500,
|
||||||
|
"preferences": ["美食", "历史文化"],
|
||||||
|
"pace": "standard"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. 关键业务规则
|
||||||
|
|
||||||
|
- 第一版限制单目的地
|
||||||
|
- 只支持 3 到 7 天
|
||||||
|
- 预算必须返回总预算与每日预算
|
||||||
|
- 失败任务必须可重试
|
||||||
|
- 生成结果需要有结构化 JSON,不能只返回自由文本
|
||||||
|
|
||||||
|
## 10. 非功能要求
|
||||||
|
|
||||||
|
- 规划结果要有稳定的结构化 JSON
|
||||||
|
- 长任务必须有状态反馈
|
||||||
|
- 外部信息源失败时要优雅降级
|
||||||
|
- 导出失败可重试
|
||||||
|
- 移动端至少可查看详情和历史计划
|
||||||
|
|
||||||
|
## 11. 开发顺序建议
|
||||||
|
|
||||||
|
1. 规划页表单与 mock 结果
|
||||||
|
2. 创建计划与详情接口
|
||||||
|
3. 历史记录与重生成
|
||||||
|
4. 导出与反馈
|
||||||
|
5. 管理后台日志页
|
||||||
|
|
||||||
|
## 12. 待确认项
|
||||||
|
|
||||||
|
- 第一版是否需要接外部天气/地图数据
|
||||||
|
- 导出先做 PDF 还是纯文本下载
|
||||||
|
- 行程生成是否需要“省钱/均衡/深度游”预设模板
|
||||||
|
- 管理端是否需要查看用户反馈详情
|
||||||
@@ -1,282 +1,120 @@
|
|||||||
# 智能旅游规划 Agent 平台
|
# 智能旅游规划 Agent 平台开发实战
|
||||||
|
|
||||||
很多人做 AI 项目时,常见问题不是模型不会调,而是应用链路不完整:能聊天,但不能真正“规划一趟旅行”。
|
这个项目不是“做一个会聊天的旅行助手”,而是围绕一份真实 PRD,把一个可执行的旅行规划产品从想法推进到可上线原型。
|
||||||
|
|
||||||
这个大作业的目标,就是把一个“会说话的 Demo”做成“可执行的产品原型”。
|
你会同时看到三件事:
|
||||||
|
|
||||||
::: tip 🎯 这次做什么?
|
- 项目要做成什么
|
||||||
打造一个 **智能旅游规划 Agent 平台**。用户输入出发地、目的地、日期、预算和偏好后,系统自动生成每日行程、预算拆分、景点与餐饮建议,并支持导出或保存计划。管理员可查看热门目的地、生成成功率和用户反馈。
|
- 如何基于 PRD 拆解并推进开发
|
||||||
|
- 最后应该交付出什么样的效果
|
||||||
|
|
||||||
|
::: tip PRD 入口
|
||||||
|
本项目的需求文档在同级页面: [查看 PRD](./PRD.md)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
<div style="margin: 32px 0;">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<StepBar :active="0" :items="[
|
<StepBar :active="0" :items="[
|
||||||
{ title: '定范围', description: '先锁定场景、角色和最小功能闭环' },
|
{ title: '看 PRD', description: '先明确页面、角色、Agent 编排、外部数据和导出范围' },
|
||||||
{ title: '搭前台', description: '把搜索、行程页、历史页先做出来' },
|
{ title: '生成骨架', description: '让 AI 先产出首页、规划页、历史页、后台页骨架' },
|
||||||
{ title: '接智能', description: '把 Agent 编排、外部数据和存储接通' },
|
{ title: '监工迭代', description: '逐页验收、补接口、修结构化输出和任务状态' },
|
||||||
{ title: '交付上线', description: '补齐后台、部署、README 和演示' }
|
{ title: '交付上线', description: '完成可演示、可运行、可继续开发的产品原型' }
|
||||||
]" />
|
]" />
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 为什么这个题目值得做?
|
## 这个项目到底在做什么?
|
||||||
|
|
||||||
因为它同时覆盖了现代 AI 应用最关键的 4 类能力:
|
这是一个旅行规划 Agent 平台:
|
||||||
|
|
||||||
- **结构化输入**:把用户偏好转成可计算参数
|
- 用户输入出发地、目的地、日期、预算和偏好
|
||||||
- **Agent 编排**:任务拆解、信息收集、行程生成与校验
|
- 系统生成每日行程、预算拆分和建议
|
||||||
- **真实业务约束**:预算、时长、交通可行性、营业时间
|
- 用户可以保存历史计划、再次生成、导出
|
||||||
- **产品化交付**:保存历史、查看详情、导出分享
|
- 管理员可以查看热门目的地、失败任务和反馈
|
||||||
|
|
||||||
做完这个项目,你学到的不只是“会调用 LLM”,而是“会做一个可落地的 AI 产品”。
|
## 开发过程怎么走?
|
||||||
|
|
||||||
## 先看全景:系统主链路是什么?
|
### 1. 先看 PRD,不要上来就写代码
|
||||||
|
|
||||||
|
先确认:
|
||||||
|
|
||||||
|
- 第一版是否只做单目的地
|
||||||
|
- 行程输出是否必须结构化
|
||||||
|
- 导出能力做多深
|
||||||
|
- 后台统计和任务日志范围是否清楚
|
||||||
|
|
||||||
|
### 2. 先让 AI 生成“骨架版”
|
||||||
|
|
||||||
|
第一轮先生成:
|
||||||
|
|
||||||
|
- 首页
|
||||||
|
- 规划页
|
||||||
|
- 行程详情页
|
||||||
|
- 历史记录页
|
||||||
|
- 管理后台页
|
||||||
|
|
||||||
|
### 3. 再进入“监工模式”
|
||||||
|
|
||||||
|
你要重点盯这几件事:
|
||||||
|
|
||||||
|
- 输入表单字段是否和 PRD 一致
|
||||||
|
- 行程输出是否真的结构化
|
||||||
|
- 预算、节奏和每日活动是否合理
|
||||||
|
- 历史计划和重生成是否闭环
|
||||||
|
- 失败任务有没有被记录
|
||||||
|
|
||||||
|
### 4. 最后做联调和上线
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
user["用户"] --> form["填写旅行需求"]
|
prd["PRD"] --> planner["规划页"]
|
||||||
form --> orchestrator["Agent 编排层"]
|
planner --> agent["Agent 编排层"]
|
||||||
orchestrator --> planner["行程生成器"]
|
agent --> model["模型调用"]
|
||||||
orchestrator --> poi["POI / 景点与餐饮数据"]
|
agent --> db["数据库"]
|
||||||
orchestrator --> weather["天气与交通信息"]
|
db --> history["历史计划"]
|
||||||
planner --> validator["预算与时间校验"]
|
db --> admin["后台统计与日志"]
|
||||||
validator --> result["输出每日行程"]
|
|
||||||
result --> db["保存到数据库"]
|
|
||||||
db --> history["历史计划页"]
|
|
||||||
result --> export["导出 PDF / 图片 / 文本"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```mermaid
|
## 怎么让 AI 帮你生成?
|
||||||
sequenceDiagram
|
|
||||||
autonumber
|
|
||||||
actor U as 用户
|
|
||||||
participant FE as 前端页面
|
|
||||||
participant API as 后端 API
|
|
||||||
participant AG as Agent 服务
|
|
||||||
participant DB as 数据库
|
|
||||||
|
|
||||||
U->>FE: 输入目的地、日期、预算、偏好
|
```text
|
||||||
FE->>API: POST /api/trips/plan
|
请基于当前 PRD,帮我生成一个智能旅游规划 Agent 平台的前端骨架。
|
||||||
API->>AG: 创建规划任务
|
|
||||||
AG->>AG: 拆解子任务并生成草案行程
|
要求:
|
||||||
AG-->>API: 返回结构化计划
|
1. 页面包括:首页、规划页、行程详情页、历史记录页、管理页
|
||||||
API->>DB: 保存 trip 与 itinerary
|
2. 规划页左侧是表单,右侧是结果预览
|
||||||
API-->>FE: 返回计划详情
|
3. 先只生成页面结构和假数据,不接真实接口
|
||||||
U->>FE: 调整偏好并再次生成
|
4. 风格要像现代 AI 产品
|
||||||
FE->>API: POST /api/trips/:id/regenerate
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 1. 定范围:先把题目收住,避免“越做越大”
|
## 怎么“监工”才有效?
|
||||||
|
|
||||||
### 角色设计
|
| 检查项 | 要看什么 |
|
||||||
|
|
||||||
| 角色 | 核心动作 |
|
|
||||||
|------|------|
|
|------|------|
|
||||||
| 普通用户 | 创建旅行计划、查看每日行程、调整偏好、保存与导出 |
|
| 页面是否对 | 页面数量、功能是否符合 PRD |
|
||||||
| 管理员 | 查看使用统计、热门城市、失败任务日志、用户反馈 |
|
| 接口是否对 | 规划、详情、历史、重生成是否闭环 |
|
||||||
|
| 输出是否对 | 行程结果是不是结构化且可读 |
|
||||||
|
| 数据是否对 | trip、itinerary、logs 是否一致 |
|
||||||
|
| 演示是否对 | 是否能演示“输入 -> 生成 -> 保存 -> 再次生成” |
|
||||||
|
|
||||||
### 核心页面
|
## 最后的预期效果
|
||||||
|
|
||||||
| 页面 | 路径 | 说明 |
|
- 一套可运行的旅行规划 Agent 平台
|
||||||
|------|------|------|
|
- 一份同级 PRD 文档
|
||||||
| 首页 | `/` | 介绍产品价值与创建入口 |
|
- 首页、规划、详情、历史、后台五类页面
|
||||||
| 规划页 | `/planner` | 填写需求并发起生成 |
|
- Agent 编排、结构化输出、历史管理、后台统计
|
||||||
| 行程详情页 | `/trips/:id` | 查看每日计划与预算拆分 |
|
- README 和演示方案
|
||||||
| 历史记录页 | `/history` | 查看过去的规划任务 |
|
|
||||||
| 管理后台 | `/admin` | 查看统计数据与任务健康状态 |
|
|
||||||
|
|
||||||
### 第一版边界(强烈建议)
|
## 验收标准
|
||||||
|
|
||||||
- 只做单人行程,不做多人协同编辑
|
| 维度 | 最低达标 |
|
||||||
- 只支持 1 个目的地,不做多城市跳转
|
|------|------|
|
||||||
- 只做 3-7 天行程,不做超长旅行计划
|
| PRD 对齐 | 页面、功能、数据结构基本符合 PRD |
|
||||||
- 先使用一种语言输出,不做多语言切换
|
| 产品闭环 | 规划、保存、历史、重生成可以跑通 |
|
||||||
- 先接一个外部信息源,避免数据接入过多导致失控
|
| 后台能力 | 任务统计和失败日志可以查看 |
|
||||||
|
| 工程完整度 | 前端、后端、数据库、模型调用链路已接通 |
|
||||||
|
| 展示能力 | 可以清楚演示“从 PRD 到成品”的过程 |
|
||||||
|
|
||||||
## 2. 搭前台:先把“用户可见闭环”跑通
|
::: tip 🚀 完成后你会得到什么?
|
||||||
|
你得到的不只是一个旅游聊天 Demo,而是一套带结构化输入、Agent 编排和任务管理的 AI 产品开发样例。
|
||||||
### 推荐技术栈
|
:::
|
||||||
|
|
||||||
- 前端:Next.js / React + TypeScript + Tailwind CSS + 组件库
|
|
||||||
- 后端:Node.js (Nest/Express) 或 Spring Boot
|
|
||||||
- 数据库:PostgreSQL / Supabase
|
|
||||||
- AI:OpenAI / Claude / Gemini 任选其一
|
|
||||||
- 可选:Redis(缓存热门目的地与提示词模板)
|
|
||||||
|
|
||||||
### 第一步:生成页面骨架
|
|
||||||
|
|
||||||
把这段提示词给你的 AI IDE:
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我生成一个“智能旅游规划 Agent 平台”的前端骨架。
|
|
||||||
|
|
||||||
技术栈:
|
|
||||||
- Next.js App Router
|
|
||||||
- TypeScript
|
|
||||||
- Tailwind CSS
|
|
||||||
|
|
||||||
页面:
|
|
||||||
1. 首页 /
|
|
||||||
2. 规划页 /planner
|
|
||||||
3. 行程详情页 /trips/[id]
|
|
||||||
4. 历史记录页 /history
|
|
||||||
5. 管理页 /admin
|
|
||||||
|
|
||||||
要求:
|
|
||||||
- 规划页左侧是需求表单,右侧是计划预览
|
|
||||||
- 行程详情按 Day1 / Day2 分段展示
|
|
||||||
- 有 loading、空状态、错误提示
|
|
||||||
- 移动端可用
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第二步:补齐规划页交互
|
|
||||||
|
|
||||||
```text
|
|
||||||
请完善 /planner 页面。
|
|
||||||
|
|
||||||
输入字段:
|
|
||||||
- 出发地
|
|
||||||
- 目的地
|
|
||||||
- 出行日期(开始/结束)
|
|
||||||
- 总预算
|
|
||||||
- 旅行偏好(自然风光/历史文化/亲子/美食)
|
|
||||||
- 每日节奏(轻松/标准/高强度)
|
|
||||||
|
|
||||||
输出区域:
|
|
||||||
- 每日行程卡片
|
|
||||||
- 预算拆分
|
|
||||||
- 交通建议
|
|
||||||
- 注意事项
|
|
||||||
|
|
||||||
要求:
|
|
||||||
- 点击“生成行程”后显示任务进度
|
|
||||||
- 失败时显示可重试按钮
|
|
||||||
- 首屏有示例数据引导
|
|
||||||
```
|
|
||||||
|
|
||||||
<div style="margin: 32px 0;">
|
|
||||||
<ClientOnly>
|
|
||||||
<StepBar :active="1" :items="[
|
|
||||||
{ title: '定范围', description: '先锁定场景、角色和最小功能闭环' },
|
|
||||||
{ title: '搭前台', description: '把搜索、行程页、历史页先做出来' },
|
|
||||||
{ title: '接智能', description: '把 Agent 编排、外部数据和存储接通' },
|
|
||||||
{ title: '交付上线', description: '补齐后台、部署、README 和演示' }
|
|
||||||
]" />
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 3. 接智能:让 Agent 真正参与业务
|
|
||||||
|
|
||||||
### 数据模型建议
|
|
||||||
|
|
||||||
```sql
|
|
||||||
users (
|
|
||||||
id uuid primary key,
|
|
||||||
email text,
|
|
||||||
role text, -- user / admin
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
trip_plans (
|
|
||||||
id uuid primary key,
|
|
||||||
user_id uuid,
|
|
||||||
origin text,
|
|
||||||
destination text,
|
|
||||||
start_date date,
|
|
||||||
end_date date,
|
|
||||||
budget numeric,
|
|
||||||
preferences jsonb,
|
|
||||||
status text, -- pending / success / failed
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
|
|
||||||
itinerary_days (
|
|
||||||
id uuid primary key,
|
|
||||||
trip_plan_id uuid,
|
|
||||||
day_index int,
|
|
||||||
title text,
|
|
||||||
activities jsonb,
|
|
||||||
day_budget numeric
|
|
||||||
)
|
|
||||||
|
|
||||||
generation_logs (
|
|
||||||
id uuid primary key,
|
|
||||||
trip_plan_id uuid,
|
|
||||||
model_name text,
|
|
||||||
prompt_snapshot text,
|
|
||||||
latency_ms int,
|
|
||||||
status text,
|
|
||||||
created_at timestamptz
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第三步:实现规划接口
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我实现 /api/trips/plan 接口。
|
|
||||||
|
|
||||||
目标:
|
|
||||||
1. 接收用户输入(目的地、日期、预算、偏好)
|
|
||||||
2. 调用 LLM 生成结构化 JSON 行程
|
|
||||||
3. 校验 JSON 字段完整性
|
|
||||||
4. 保存到 trip_plans 和 itinerary_days 表
|
|
||||||
5. 返回给前端展示
|
|
||||||
|
|
||||||
要求:
|
|
||||||
- 明确 DTO 和校验规则
|
|
||||||
- 返回统一错误码
|
|
||||||
- 记录模型调用耗时与失败日志
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第四步:实现再生成与优化
|
|
||||||
|
|
||||||
```text
|
|
||||||
请帮我实现“微调行程”接口 /api/trips/:id/regenerate。
|
|
||||||
|
|
||||||
用户可输入:
|
|
||||||
- “预算再低 20%”
|
|
||||||
- “减少步行”
|
|
||||||
- “多加亲子场景”
|
|
||||||
|
|
||||||
要求:
|
|
||||||
- 保留旧版本行程
|
|
||||||
- 生成新版本并对比差异
|
|
||||||
- 前端支持一键切换版本
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. 上线与交付
|
|
||||||
|
|
||||||
### 交付物
|
|
||||||
|
|
||||||
- 完整项目仓库(前后端或单体)
|
|
||||||
- 可访问演示链接
|
|
||||||
- README(安装、配置、启动、部署、排障)
|
|
||||||
- 60 秒左右演示视频
|
|
||||||
- 至少 4 张截图:首页、规划页、结果页、管理页
|
|
||||||
|
|
||||||
### 验收标准
|
|
||||||
|
|
||||||
| 维度 | 最低达标 | 加分项 |
|
|
||||||
|------|------|------|
|
|
||||||
| 功能闭环 | 可创建计划、查看结果、保存历史 | 可做二次优化并保留版本 |
|
|
||||||
| 智能质量 | 输出结构化、基本可执行 | 有预算校验和冲突提示 |
|
|
||||||
| 工程质量 | 接口清晰、错误可追踪 | 有缓存与性能优化 |
|
|
||||||
| 产品体验 | loading/空态/错误态完整 | 支持导出分享 |
|
|
||||||
| 运维交付 | 可部署、文档可复现 | 有后台统计看板 |
|
|
||||||
|
|
||||||
## 提交前最后检查
|
|
||||||
|
|
||||||
<el-card shadow="hover" style="margin: 20px 0; border-radius: 12px;">
|
|
||||||
<template #header>
|
|
||||||
<div style="font-weight: bold; font-size: 16px;">提交前最后看一眼</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<ul style="list-style-type: none; padding-left: 0;">
|
|
||||||
<li><label><input type="checkbox" disabled /> 用户可以创建并成功生成一份行程</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 行程结果按天展示且可读</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 生成记录已写入数据库并可回看</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 接口失败时有可理解错误提示</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 管理后台可查看基础统计</label></li>
|
|
||||||
<li><label><input type="checkbox" disabled /> 项目可部署且 README 可复现</label></li>
|
|
||||||
</ul>
|
|
||||||
</el-card>
|
|
||||||
|
|||||||
@@ -137,32 +137,32 @@ flowchart LR
|
|||||||
<NavGrid>
|
<NavGrid>
|
||||||
<NavCard
|
<NavCard
|
||||||
href="/zh-cn/stage-2/assignments/modern-landing-page/"
|
href="/zh-cn/stage-2/assignments/modern-landing-page/"
|
||||||
title="扩展作业:现代网页落地页"
|
title="扩展作业:现代 Web 落地页工程"
|
||||||
description="练习价值表达、转化路径、CTA 设计与基础埋点,做一个真正能承接流量的页面"
|
description="练习价值表达、转化路径、CTA 设计与基础埋点,做一个真正能承接流量的页面"
|
||||||
/>
|
/>
|
||||||
<NavCard
|
<NavCard
|
||||||
href="/zh-cn/stage-2/assignments/custom-dify-agent-platform/"
|
href="/zh-cn/stage-2/assignments/custom-dify-agent-platform/"
|
||||||
title="扩展作业:自制 Dify 智能体平台"
|
title="扩展作业:类 Dify 智能体编排平台"
|
||||||
description="实现智能体管理、对话、日志与权限控制,做一个最小可用的 AI 平台"
|
description="实现智能体管理、对话、日志与权限控制,做一个最小可用的 AI 平台"
|
||||||
/>
|
/>
|
||||||
<NavCard
|
<NavCard
|
||||||
href="/zh-cn/stage-2/assignments/travel-planning-agent-platform/"
|
href="/zh-cn/stage-2/assignments/travel-planning-agent-platform/"
|
||||||
title="扩展作业:智能旅游规划 Agent 平台"
|
title="扩展作业:智能旅游规划 Agent 编排平台"
|
||||||
description="围绕结构化输入、Agent 编排和历史计划管理,做一个可执行的 AI 旅行规划产品"
|
description="围绕结构化输入、Agent 编排和历史计划管理,做一个可执行的 AI 旅行规划产品"
|
||||||
/>
|
/>
|
||||||
<NavCard
|
<NavCard
|
||||||
href="/zh-cn/stage-2/assignments/movie-recommendation-springboot/"
|
href="/zh-cn/stage-2/assignments/movie-recommendation-springboot/"
|
||||||
title="扩展作业:电影推荐网(Spring Boot)"
|
title="扩展作业:Spring Boot 电影推荐系统"
|
||||||
description="结合 Spring Boot、评分收藏与可解释推荐,完成一个完整推荐系统原型"
|
description="结合 Spring Boot、评分收藏与可解释推荐,完成一个完整推荐系统原型"
|
||||||
/>
|
/>
|
||||||
<NavCard
|
<NavCard
|
||||||
href="/zh-cn/stage-2/assignments/simple-grocery-microservices/"
|
href="/zh-cn/stage-2/assignments/simple-grocery-microservices/"
|
||||||
title="扩展作业:简单买菜微服务网站"
|
title="扩展作业:生鲜电商微服务系统"
|
||||||
description="练习服务拆分、网关转发、库存与订单协作,体验从单体到微服务的工程思路"
|
description="练习服务拆分、网关转发、库存与订单协作,体验从单体到微服务的工程思路"
|
||||||
/>
|
/>
|
||||||
<NavCard
|
<NavCard
|
||||||
href="/zh-cn/stage-2/assignments/traffic-data-visualization-go/"
|
href="/zh-cn/stage-2/assignments/traffic-data-visualization-go/"
|
||||||
title="扩展作业:交通大数据可视化分析(Go)"
|
title="扩展作业:Go 交通数据分析与可视化平台"
|
||||||
description="从数据接入、窗口聚合到趋势看板与告警,做一个完整的数据产品原型"
|
description="从数据接入、窗口聚合到趋势看板与告警,做一个完整的数据产品原型"
|
||||||
/>
|
/>
|
||||||
</NavGrid>
|
</NavGrid>
|
||||||
|
|||||||
Reference in New Issue
Block a user