Checkpoint: Tennis Training Hub v1.0 - 完整功能版本:用户名登录、AI训练计划生成、MediaPipe视频姿势识别、击球统计、挥拍速度分析、NTRP自动评分系统、训练进度追踪、视频库管理、AI矫正建议
这个提交包含在:
@@ -1,31 +1,150 @@
|
||||
import { useAuth } from "@/_core/hooks/useAuth";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { getLoginUrl } from "@/const";
|
||||
import { Streamdown } from 'streamdown';
|
||||
import { useLocation, Redirect } from "wouter";
|
||||
import {
|
||||
Target, Video, Award, TrendingUp, Zap, Activity,
|
||||
ChevronRight, Footprints, BarChart3
|
||||
} from "lucide-react";
|
||||
|
||||
/**
|
||||
* All content in this page are only for example, replace with your own feature implementation
|
||||
* When building pages, remember your instructions in Frontend Workflow, Frontend Best Practices, Design Guide and Common Pitfalls
|
||||
*/
|
||||
export default function Home() {
|
||||
// The userAuth hooks provides authentication state
|
||||
// To implement login/logout functionality, simply call logout() or redirect to getLoginUrl()
|
||||
let { user, loading, error, isAuthenticated, logout } = useAuth();
|
||||
const { user, loading, isAuthenticated } = useAuth();
|
||||
const [, setLocation] = useLocation();
|
||||
|
||||
// If theme is switchable in App.tsx, we can implement theme toggling like this:
|
||||
// const { theme, toggleTheme } = useTheme();
|
||||
if (loading) return null;
|
||||
if (isAuthenticated) return <Redirect to="/dashboard" />;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<main>
|
||||
{/* Example: lucide-react for icons */}
|
||||
<Loader2 className="animate-spin" />
|
||||
Example Page
|
||||
{/* Example: Streamdown for markdown rendering */}
|
||||
<Streamdown>Any **markdown** content</Streamdown>
|
||||
<Button variant="default">Example Button</Button>
|
||||
</main>
|
||||
<div className="min-h-screen bg-gradient-to-b from-green-50 via-background to-emerald-50/30">
|
||||
{/* Hero */}
|
||||
<header className="container py-6 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Target className="h-6 w-6 text-primary" />
|
||||
<span className="font-bold text-lg tracking-tight">Tennis Training Hub</span>
|
||||
</div>
|
||||
<Button onClick={() => setLocation("/login")} variant="default" size="sm">
|
||||
开始使用
|
||||
</Button>
|
||||
</header>
|
||||
|
||||
<section className="container py-16 md:py-24">
|
||||
<div className="max-w-3xl mx-auto text-center">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 text-primary text-sm font-medium mb-6">
|
||||
<Zap className="h-3.5 w-3.5" />
|
||||
AI驱动的网球训练助手
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight leading-tight">
|
||||
在家也能提升
|
||||
<span className="text-primary block mt-1">网球技术水平</span>
|
||||
</h1>
|
||||
<p className="text-lg text-muted-foreground mt-6 max-w-xl mx-auto leading-relaxed">
|
||||
只需一支球拍,通过AI姿势识别和智能训练计划,在家高效训练。
|
||||
实时分析挥拍动作,自动评分,持续进步。
|
||||
</p>
|
||||
<div className="flex items-center justify-center gap-3 mt-8">
|
||||
<Button onClick={() => setLocation("/login")} size="lg" className="gap-2 h-12 px-6">
|
||||
免费开始训练
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features */}
|
||||
<section className="container py-16">
|
||||
<h2 className="text-2xl font-bold text-center mb-12">核心功能</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-5xl mx-auto">
|
||||
{[
|
||||
{
|
||||
icon: Video,
|
||||
title: "AI姿势识别",
|
||||
desc: "基于MediaPipe的浏览器端实时姿势分析,识别33个身体关键点,精准评估挥拍动作",
|
||||
color: "bg-blue-50 text-blue-600",
|
||||
},
|
||||
{
|
||||
icon: Target,
|
||||
title: "智能训练计划",
|
||||
desc: "根据您的水平和分析结果,AI自动生成和调整个性化训练方案,只需球拍即可在家训练",
|
||||
color: "bg-green-50 text-green-600",
|
||||
},
|
||||
{
|
||||
icon: Award,
|
||||
title: "NTRP自动评分",
|
||||
desc: "基于美国网球协会标准,从5个维度综合评估您的技术水平,自动更新评分",
|
||||
color: "bg-purple-50 text-purple-600",
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: "击球统计分析",
|
||||
desc: "自动检测击球次数、挥拍速度、击球一致性,量化每次训练效果",
|
||||
color: "bg-orange-50 text-orange-600",
|
||||
},
|
||||
{
|
||||
icon: Footprints,
|
||||
title: "运动轨迹追踪",
|
||||
desc: "记录身体重心移动轨迹,分析脚步移动模式,提升步法灵活性",
|
||||
color: "bg-teal-50 text-teal-600",
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
title: "进度可视化",
|
||||
desc: "直观展示训练历史、能力提升趋势和评分变化,激励持续进步",
|
||||
color: "bg-indigo-50 text-indigo-600",
|
||||
},
|
||||
].map((feature) => (
|
||||
<div key={feature.title} className="p-6 rounded-2xl border bg-card hover:shadow-md transition-shadow">
|
||||
<div className={`h-12 w-12 rounded-xl ${feature.color} flex items-center justify-center mb-4`}>
|
||||
<feature.icon className="h-6 w-6" />
|
||||
</div>
|
||||
<h3 className="font-semibold text-base mb-2">{feature.title}</h3>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">{feature.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* How it works */}
|
||||
<section className="container py-16">
|
||||
<h2 className="text-2xl font-bold text-center mb-12">使用流程</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 max-w-4xl mx-auto">
|
||||
{[
|
||||
{ step: "1", title: "输入用户名", desc: "无需注册,输入用户名即可开始" },
|
||||
{ step: "2", title: "生成训练计划", desc: "选择水平,AI生成个性化方案" },
|
||||
{ step: "3", title: "上传训练视频", desc: "录制挥拍视频并上传分析" },
|
||||
{ step: "4", title: "获取评分建议", desc: "查看分析结果和矫正建议" },
|
||||
].map((item) => (
|
||||
<div key={item.step} className="text-center">
|
||||
<div className="h-12 w-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-lg font-bold mx-auto mb-3">
|
||||
{item.step}
|
||||
</div>
|
||||
<h3 className="font-semibold text-sm mb-1">{item.title}</h3>
|
||||
<p className="text-xs text-muted-foreground">{item.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="container py-16">
|
||||
<div className="max-w-2xl mx-auto text-center p-8 rounded-2xl bg-primary/5">
|
||||
<h2 className="text-2xl font-bold mb-3">准备好提升网球技术了吗?</h2>
|
||||
<p className="text-muted-foreground mb-6">完全免费,无需注册,输入用户名即可开始</p>
|
||||
<Button onClick={() => setLocation("/login")} size="lg" className="gap-2">
|
||||
立即开始
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="container py-8 border-t">
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
||||
<div className="flex items-center gap-2">
|
||||
<Target className="h-4 w-4" />
|
||||
<span>Tennis Training Hub</span>
|
||||
</div>
|
||||
<span>AI驱动的在家网球训练助手</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户