演示模式
无需登录即可试用 ProductReady - 使用示例数据探索功能
演示模式
ProductReady 包含演示模式,让您无需创建账户或设置数据库即可探索所有功能。非常适合:
- 🎯 快速探索 - 立即查看功能实际效果
- 👥 演示展示 - 向利益相关者展示您的应用
- 🧪 测试 - 无需真实数据即可尝试 UI 和工作流程
- 📚 学习 - 在实施前了解功能如何工作
无需设置! 演示模式使用模拟数据工作 - 无需数据库,无需身份验证。
如何使用演示模式
激活演示模式
在任何 URL 添加 ?demo=1:
http://localhost:3000/dashboard?demo=1
http://localhost:3000/agent?demo=1或在登录页面使用演示用户登录(见下文)。
演示模式包含的内容
激活演示模式后,您将看到:
✅ 示例数据
- 5 个演示代理任务(各种状态:待处理、进行中、已完成、失败)
- 8 篇示例博客文章(已发布和草稿)
- 3 个演示用户
✅ 完整 UI 访问
- 带指标的仪表板
- 代理任务管理
- 博客文章列表
- 所有导航和布局
✅ 只读操作
- 查看所有演示内容
- 浏览和过滤
- 查看 UI 交互
⚠️ 限制
- 无法创建/编辑/删除真实数据
- 更改会显示警告但不会持久化
- 数据库操作返回模拟数据
演示用户登录
登录页面包含**"尝试演示模式"**按钮,无需凭据即可立即访问。
转到登录页面
访问 /sign-in 或从登陆页面点击"登录"。
点击"尝试演示模式"
在登录表单下方查找蓝色按钮:
┌─────────────────────────┐
│ 登录到 ProductReady │
├─────────────────────────┤
│ 邮箱: _______________ │
│ 密码: ___________ │
│ [登录] │
│ │
│ ─────── 或 ─────── │
│ │
│ [尝试演示模式] ← 这里 │
└─────────────────────────┘演示数据示例
演示代理任务
演示模式包含 5 个示例代理任务:
// 示例演示代理任务
[
{
title: "创建带定价部分的落地页",
status: "completed",
priority: "high",
result: "成功生成落地页..."
},
{
title: "生成关于 Next.js 16 的博客文章",
status: "in_progress",
priority: "high"
},
{
title: "创建带图表的仪表板组件",
status: "pending",
priority: "medium"
},
// ... 更多任务
]演示博客文章(示例功能)
8 篇涵盖各种主题的示例文章:
- "开始使用 ProductReady"
- "理解 tRPC 类型安全"
- "Drizzle ORM 最佳实践"
- "使用 CSS 变量构建设计系统"
- 等等...
注意:博客文章是一个示例功能,用于演示 CRUD 操作。您可以删除此功能或用自己的业务逻辑替换它。
演示用户
3 个用于测试的演示用户:
- Alice Johnson (
alice@example.com) - Bob Smith (
bob@example.com) - Carol Williams (
carol@example.com)
在代码中使用演示模式
检测演示模式
import { isDemoMode } from '~/lib/demo';
export function MyComponent() {
const searchParams = useSearchParams();
const isDemo = isDemoMode(searchParams);
if (isDemo) {
return <DemoBanner />;
}
// 正常组件
}使用演示模式的 tRPC
所有 tRPC 路由都会根据上下文自动检测演示模式:
// 查询会根据 URL/请求头自动处理演示模式
const { data } = trpc.agentTasks.list.useQuery({
limit: 20,
});
// 使用演示模式检查创建
const createTask = trpc.agentTasks.create.useMutation({
onMutate: () => {
if (isDemo) {
alert('演示模式:登录以创建真实代理任务');
return;
}
}
});服务器端演示检测
// 在 tRPC 路由中
export const myRouter = createTRPCRouter({
list: publicProcedure
.input(z.object({
// 输入中不需要 demo 参数
}))
.query(async ({ ctx, input }) => {
// 如果上下文指示演示模式,则返回模拟数据
if (ctx.isDemo) {
return getDemoData();
}
// 真实数据库查询
return ctx.db.select().from(myTable);
}),
});演示横幅组件
演示模式显示蓝色横幅以指示示例数据:
{isDemo && (
<div className="rounded-lg border border-blue-200 bg-blue-50 p-4">
<div className="flex items-center gap-2">
<Bot className="h-5 w-5 text-blue-600" />
<div>
<p className="text-sm font-medium text-blue-900">
演示模式已激活
</p>
<p className="text-sm text-blue-700">
正在查看示例数据。登录以创建真实内容。
</p>
</div>
</div>
</div>
)}创建您自己的演示数据
在 src/lib/demo.ts 中添加演示数据:
// 定义您的演示数据
export const DEMO_PRODUCTS: Product[] = [
{
id: 1,
name: "入门计划",
price: 9.99,
features: ["功能 1", "功能 2"],
},
// ... 更多项目
];
// 导出获取函数
export function getDemoProducts(): Product[] {
return DEMO_PRODUCTS;
}在 tRPC 路由中使用:
import { getDemoProducts } from '~/lib/demo';
export const productsRouter = createTRPCRouter({
list: publicProcedure
.input(z.object({ /* ... */ }))
.query(async ({ ctx, input }) => {
if (ctx.isDemo) {
return getDemoProducts();
}
return ctx.db.select().from(products);
}),
});禁用演示模式
在生产环境中禁用演示模式:
// src/middleware.ts
export function middleware(request: NextRequest) {
const { searchParams } = request.nextUrl;
// 在生产环境中禁用演示模式
if (process.env.NODE_ENV === 'production' && searchParams.get('demo')) {
const url = request.nextUrl.clone();
url.searchParams.delete('demo');
return NextResponse.redirect(url);
}
return NextResponse.next();
}或隐藏演示按钮:
{process.env.NODE_ENV !== 'production' && (
<Button onClick={goToDemo}>尝试演示模式</Button>
)}最佳实践
✅ 推荐做法
- 显示演示横幅 - 明确指示何时查看示例数据
- 禁用变更操作 - 向用户显示警告而不是错误
- 使用真实数据 - 使演示令人信服
- 匹配真实模式 - 保持演示类型与数据库同步
- 测试演示模式 - 确保无需数据库即可工作
❌ 避免做法
- 不要混合演示和真实数据 - 保持它们分开
- 不要跳过横幅 - 用户必须知道这是演示模式
- 不要允许部分保存 - 演示中全有或全无
- 不要暴露敏感数据 - 使用通用演示内容
- 不要忘记文档 - 解释什么被模拟
下一步
演示模式非常适合无风险地探索 ProductReady。准备好后,按照快速开始指南设置您自己的应用!