docs(skills): 添加 Better Auth 最佳实践与安全配置指南

This commit is contained in:
asgerzhou
2026-07-17 15:59:38 +08:00
commit 57628c04d6
72 changed files with 14239 additions and 0 deletions
+203
View File
@@ -0,0 +1,203 @@
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
Activity,
DollarSign,
Users,
TrendingUp,
ArrowUpRight,
ArrowDownRight,
} from "lucide-react";
const stats = [
{
title: "总收入",
value: "¥ 128,430",
change: "+12.5%",
trend: "up" as const,
icon: DollarSign,
desc: "较上月",
},
{
title: "活跃用户",
value: "2,840",
change: "+8.2%",
trend: "up" as const,
icon: Users,
desc: "较上周",
},
{
title: "转化率",
value: "3.6%",
change: "-0.4%",
trend: "down" as const,
icon: TrendingUp,
desc: "较上月",
},
{
title: "实时会话",
value: "147",
change: "+23",
trend: "up" as const,
icon: Activity,
desc: "当前在线",
},
];
const recentOrders = [
{
id: "ORD-7821",
customer: "张三",
email: "zhangsan@example.com",
amount: "¥ 1,299",
status: "已完成",
},
{
id: "ORD-7820",
customer: "李四",
email: "lisi@example.com",
amount: "¥ 899",
status: "处理中",
},
{
id: "ORD-7819",
customer: "王五",
email: "wangwu@example.com",
amount: "¥ 2,499",
status: "已完成",
},
{
id: "ORD-7818",
customer: "赵六",
email: "zhaoliu@example.com",
amount: "¥ 599",
status: "已取消",
},
];
function statusVariant(status: string) {
if (status === "已完成") return "default" as const;
if (status === "处理中") return "secondary" as const;
return "destructive" as const;
}
export default function AdminDashboardPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-1">
<h1 className="text-2xl font-semibold tracking-tight"></h1>
<p className="text-sm text-muted-foreground">
</p>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{stats.map((stat) => (
<Card key={stat.title} className="gap-2">
<CardHeader>
<div className="flex items-center justify-between">
<CardDescription>{stat.title}</CardDescription>
<stat.icon className="size-4 text-muted-foreground" />
</div>
<CardTitle className="text-2xl font-semibold tabular-nums">
{stat.value}
</CardTitle>
</CardHeader>
<CardFooter className="text-xs text-muted-foreground">
<span
className={`inline-flex items-center gap-1 font-medium ${
stat.trend === "up"
? "text-emerald-600"
: "text-destructive"
}`}
>
{stat.trend === "up" ? (
<ArrowUpRight className="size-3" />
) : (
<ArrowDownRight className="size-3" />
)}
{stat.change}
</span>
<span className="ml-1">{stat.desc}</span>
</CardFooter>
</Card>
))}
</div>
<div className="grid gap-4 lg:grid-cols-7">
<Card className="lg:col-span-4">
<CardHeader>
<CardTitle></CardTitle>
<CardDescription> 5 </CardDescription>
<CardAction>
<Button variant="ghost" size="sm">
</Button>
</CardAction>
</CardHeader>
<CardContent>
<div className="divide-y">
{recentOrders.map((order) => (
<div
key={order.id}
className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
>
<div className="flex flex-col">
<span className="text-sm font-medium">
{order.customer}
</span>
<span className="text-xs text-muted-foreground">
{order.email}
</span>
</div>
<div className="flex items-center gap-3">
<Badge variant={statusVariant(order.status)}>
{order.status}
</Badge>
<span className="text-sm font-medium tabular-nums">
{order.amount}
</span>
</div>
</div>
))}
</div>
</CardContent>
</Card>
<Card className="lg:col-span-3">
<CardHeader>
<CardTitle></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent className="grid gap-2">
<Button variant="outline" className="justify-start">
<Users className="size-4" />
</Button>
<Button variant="outline" className="justify-start">
<DollarSign className="size-4" />
</Button>
<Button variant="outline" className="justify-start">
<Activity className="size-4" />
</Button>
<Button variant="outline" className="justify-start">
<TrendingUp className="size-4" />
</Button>
</CardContent>
</Card>
</div>
</div>
);
}