383 lines
16 KiB
TypeScript
383 lines
16 KiB
TypeScript
import { DashboardShell } from "@/components/dashboard-shell"
|
||
import { DashboardHeader } from "@/components/dashboard-header"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||
import { Badge } from "@/components/ui/badge"
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||
import { ArrowLeft, Edit, AlertTriangle, FileText, Plus, Download } from "lucide-react"
|
||
import Link from "next/link"
|
||
import { AddPrintBatchDialog } from "@/components/props/add-print-batch-dialog"
|
||
import { ExportCardsDialog } from "@/components/props/export-cards-dialog"
|
||
|
||
// Mock data for the prop details
|
||
const propData = {
|
||
PRP001: {
|
||
id: "PRP001",
|
||
name: "魔法麦克风",
|
||
type: "演出道具",
|
||
rarity: "稀有",
|
||
description: "洛天依的经典原创道具,可以增强歌声的魔力,让听众更加沉浸在音乐中。",
|
||
releaseDate: "2023-11-15",
|
||
status: "已发布",
|
||
activatedCount: 1245,
|
||
printedCount: 2000,
|
||
image: "/placeholder.svg?height=300&width=300",
|
||
batches: [
|
||
{
|
||
id: "B001",
|
||
date: "2023-09-01",
|
||
quantity: 1000,
|
||
startId: "PRP001-0001",
|
||
endId: "PRP001-1000",
|
||
status: "已激活",
|
||
activatedCount: 980,
|
||
},
|
||
{
|
||
id: "B002",
|
||
date: "2023-12-15",
|
||
quantity: 1000,
|
||
startId: "PRP001-1001",
|
||
endId: "PRP001-2000",
|
||
status: "已激活",
|
||
activatedCount: 265,
|
||
},
|
||
],
|
||
},
|
||
PRP002: {
|
||
id: "PRP002",
|
||
name: "星光魔杖",
|
||
type: "互动道具",
|
||
rarity: "史诗",
|
||
description: "挥舞魔杖可以创造出美丽的星光效果,增加互动时的好感度。",
|
||
releaseDate: "2023-12-01",
|
||
status: "已发布",
|
||
activatedCount: 876,
|
||
printedCount: 1500,
|
||
image: "/placeholder.svg?height=300&width=300",
|
||
batches: [
|
||
{
|
||
id: "B003",
|
||
date: "2023-05-10",
|
||
quantity: 1500,
|
||
startId: "PRP002-0001",
|
||
endId: "PRP002-1500",
|
||
status: "已激活",
|
||
activatedCount: 876,
|
||
},
|
||
],
|
||
},
|
||
PRP003: {
|
||
id: "PRP003",
|
||
name: "音乐盒",
|
||
type: "收藏品",
|
||
rarity: "传说",
|
||
description: "精美的音乐盒,打开后会播放洛天依的经典歌曲,是珍贵的收藏品。",
|
||
releaseDate: "2024-01-10",
|
||
status: "已发布",
|
||
activatedCount: 532,
|
||
printedCount: 1000,
|
||
image: "/placeholder.svg?height=300&width=300",
|
||
batches: [
|
||
{
|
||
id: "B004",
|
||
date: "2023-11-15",
|
||
quantity: 1000,
|
||
startId: "PRP003-0001",
|
||
endId: "PRP003-1000",
|
||
status: "已激活",
|
||
activatedCount: 532,
|
||
},
|
||
],
|
||
},
|
||
PRP004: {
|
||
id: "PRP004",
|
||
name: "虚拟相机",
|
||
type: "互动道具",
|
||
rarity: "稀有",
|
||
description: "可以捕捉洛天依的精彩瞬间,保存为虚拟照片。",
|
||
releaseDate: "2024-02-05",
|
||
status: "已发布",
|
||
activatedCount: 967,
|
||
printedCount: 2000,
|
||
image: "/placeholder.svg?height=300&width=300",
|
||
batches: [
|
||
{
|
||
id: "B005",
|
||
date: "2024-01-05",
|
||
quantity: 2000,
|
||
startId: "PRP004-0001",
|
||
endId: "PRP004-2000",
|
||
status: "已激活",
|
||
activatedCount: 967,
|
||
},
|
||
],
|
||
},
|
||
PRP005: {
|
||
id: "PRP005",
|
||
name: "节日礼盒",
|
||
type: "限定道具",
|
||
rarity: "史诗",
|
||
description: "节日限定礼盒,内含多种惊喜道具和装饰品。",
|
||
releaseDate: "",
|
||
status: "未发布",
|
||
activatedCount: 0,
|
||
printedCount: 1000,
|
||
image: "/placeholder.svg?height=300&width=300",
|
||
batches: [
|
||
{
|
||
id: "B007",
|
||
date: "2024-03-20",
|
||
quantity: 1000,
|
||
startId: "PRP005-0001",
|
||
endId: "PRP005-1000",
|
||
status: "未激活",
|
||
activatedCount: 0,
|
||
},
|
||
],
|
||
},
|
||
}
|
||
|
||
export default function PropDetailPage({ params }: { params: { id: string } }) {
|
||
const prop = propData[params.id as keyof typeof propData]
|
||
|
||
if (!prop) {
|
||
return (
|
||
<DashboardShell>
|
||
<div className="flex flex-col items-center justify-center h-[60vh]">
|
||
<AlertTriangle className="h-16 w-16 text-red-500 mb-4" />
|
||
<h1 className="text-2xl font-bold mb-2">道具不存在</h1>
|
||
<p className="text-gray-500 mb-6">找不到ID为 {params.id} 的道具</p>
|
||
<Button asChild>
|
||
<Link href="/props">
|
||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||
返回道具列表
|
||
</Link>
|
||
</Button>
|
||
</div>
|
||
</DashboardShell>
|
||
)
|
||
}
|
||
|
||
const isPublished = prop.status === "已发布"
|
||
const activationRate = prop.printedCount > 0 ? Math.round((prop.activatedCount / prop.printedCount) * 100) : 0
|
||
|
||
return (
|
||
<DashboardShell>
|
||
<div className="absolute top-0 right-0 w-1/2 h-48 bg-gradient-to-bl from-purple-200 via-pink-200 to-transparent opacity-20 rounded-bl-full" />
|
||
|
||
<div className="flex items-center mb-6">
|
||
<Button variant="ghost" size="sm" className="mr-4" asChild>
|
||
<Link href="/props">
|
||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||
返回列表
|
||
</Link>
|
||
</Button>
|
||
<DashboardHeader heading={prop.name} text={`道具ID: ${prop.id}`}>
|
||
<div className="flex space-x-2 ml-auto">
|
||
{!isPublished && (
|
||
<Button
|
||
asChild
|
||
className="bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700 transition-all duration-300 shadow-md hover:shadow-lg"
|
||
>
|
||
<Link href={`/props/edit/${params.id}`}>
|
||
<Edit className="mr-2 h-4 w-4" />
|
||
编辑道具
|
||
</Link>
|
||
</Button>
|
||
)}
|
||
<ExportCardsDialog propId={prop.id} />
|
||
</div>
|
||
</DashboardHeader>
|
||
</div>
|
||
|
||
<Tabs defaultValue="details" className="w-full">
|
||
<TabsList className="grid w-full md:w-auto grid-cols-2 md:grid-cols-3 mb-4">
|
||
<TabsTrigger value="details">道具详情</TabsTrigger>
|
||
<TabsTrigger value="batches">批次管理</TabsTrigger>
|
||
<TabsTrigger value="analytics">数据分析</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="details" className="space-y-6">
|
||
<div className="grid gap-6 md:grid-cols-3">
|
||
<Card className="md:col-span-1 border-none shadow-lg bg-white">
|
||
<CardHeader>
|
||
<CardTitle className="text-lg font-bold">道具预览</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="flex justify-center">
|
||
<div className="relative w-full aspect-square max-w-[300px] rounded-lg overflow-hidden bg-gray-100 flex items-center justify-center">
|
||
<img src={prop.image || "/placeholder.svg"} alt={prop.name} className="object-cover" />
|
||
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-3">
|
||
<Badge className={`${isPublished ? "bg-green-500" : "bg-gray-500"}`}>{prop.status}</Badge>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card className="md:col-span-2 border-none shadow-lg bg-gradient-to-br from-white to-purple-50">
|
||
<CardHeader>
|
||
<CardTitle className="text-lg font-bold">道具详情</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-1">
|
||
<p className="text-sm font-medium text-gray-500">道具类型</p>
|
||
<p className="font-medium">{prop.type}</p>
|
||
</div>
|
||
<div className="space-y-1">
|
||
<p className="text-sm font-medium text-gray-500">稀有度</p>
|
||
<p className="font-medium">{prop.rarity}</p>
|
||
</div>
|
||
<div className="space-y-1">
|
||
<p className="text-sm font-medium text-gray-500">发布日期</p>
|
||
<p className="font-medium">{prop.releaseDate || "尚未发布"}</p>
|
||
</div>
|
||
<div className="space-y-1">
|
||
<p className="text-sm font-medium text-gray-500">激活数量</p>
|
||
<p className="font-medium">{prop.activatedCount}</p>
|
||
</div>
|
||
<div className="space-y-1">
|
||
<p className="text-sm font-medium text-gray-500">印刷总数</p>
|
||
<p className="font-medium">{prop.printedCount}</p>
|
||
</div>
|
||
<div className="space-y-1">
|
||
<p className="text-sm font-medium text-gray-500">激活率</p>
|
||
<p className="font-medium">{activationRate}%</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-6">
|
||
<p className="text-sm font-medium text-gray-500 mb-2">道具描述</p>
|
||
<p className="text-gray-700">{prop.description}</p>
|
||
</div>
|
||
|
||
{isPublished && (
|
||
<div className="mt-6 p-3 bg-amber-50 border border-amber-200 rounded-lg flex items-start">
|
||
<AlertTriangle className="h-5 w-5 text-amber-500 mr-2 flex-shrink-0 mt-0.5" />
|
||
<p className="text-sm text-amber-700">该道具已发布,基本属性不可修改。您仍可以增加印刷数量。</p>
|
||
</div>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="batches" className="space-y-6">
|
||
<Card className="border-none shadow-lg bg-gradient-to-br from-white to-blue-50">
|
||
<CardHeader className="flex flex-row items-center justify-between">
|
||
<div>
|
||
<CardTitle className="text-lg font-bold">印刷批次管理</CardTitle>
|
||
<CardDescription>管理道具卡牌的印刷批次和卡牌ID</CardDescription>
|
||
</div>
|
||
<AddPrintBatchDialog propId={prop.id} isPublished={isPublished} />
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="rounded-md border">
|
||
<table className="w-full">
|
||
<thead>
|
||
<tr className="bg-gray-50 border-b">
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">批次ID</th>
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">创建日期</th>
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">数量</th>
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">起始ID</th>
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">结束ID</th>
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">状态</th>
|
||
<th className="py-3 px-4 text-left text-sm font-medium text-gray-500">激活数</th>
|
||
<th className="py-3 px-4 text-right text-sm font-medium text-gray-500">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{prop.batches.map((batch) => (
|
||
<tr key={batch.id} className="border-b hover:bg-gray-50">
|
||
<td className="py-3 px-4 text-sm font-medium">{batch.id}</td>
|
||
<td className="py-3 px-4 text-sm">{batch.date}</td>
|
||
<td className="py-3 px-4 text-sm">{batch.quantity}</td>
|
||
<td className="py-3 px-4 text-sm font-mono text-xs">{batch.startId}</td>
|
||
<td className="py-3 px-4 text-sm font-mono text-xs">{batch.endId}</td>
|
||
<td className="py-3 px-4 text-sm">
|
||
<Badge className={`${batch.status === "已激活" ? "bg-green-500" : "bg-gray-500"}`}>
|
||
{batch.status}
|
||
</Badge>
|
||
</td>
|
||
<td className="py-3 px-4 text-sm">{batch.activatedCount}</td>
|
||
<td className="py-3 px-4 text-right">
|
||
<div className="flex justify-end space-x-2">
|
||
<Button variant="ghost" size="sm" className="h-8 hover:bg-blue-50 hover:text-blue-600">
|
||
<FileText className="h-4 w-4 mr-1" />
|
||
查看
|
||
</Button>
|
||
<Button variant="ghost" size="sm" className="h-8 hover:bg-green-50 hover:text-green-600">
|
||
<Download className="h-4 w-4 mr-1" />
|
||
导出
|
||
</Button>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card className="border-none shadow-lg bg-white">
|
||
<CardHeader>
|
||
<CardTitle className="text-lg font-bold">批次操作</CardTitle>
|
||
<CardDescription>批量管理卡牌批次</CardDescription>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="flex flex-wrap gap-4">
|
||
<Button variant="outline" className="border-blue-200 hover:bg-blue-50 hover:text-blue-700">
|
||
<Download className="mr-2 h-4 w-4" />
|
||
导出所有批次
|
||
</Button>
|
||
<Button variant="outline" className="border-purple-200 hover:bg-purple-50 hover:text-purple-700">
|
||
<Plus className="mr-2 h-4 w-4" />
|
||
批量添加批次
|
||
</Button>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="analytics" className="space-y-6">
|
||
<Card className="border-none shadow-lg bg-white">
|
||
<CardHeader>
|
||
<CardTitle className="text-lg font-bold">激活数据分析</CardTitle>
|
||
<CardDescription>道具卡牌激活情况统计</CardDescription>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="h-[300px] flex items-center justify-center bg-gray-50 rounded-lg">
|
||
<p className="text-gray-500">激活数据图表将在此显示</p>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<div className="grid gap-6 md:grid-cols-2">
|
||
<Card className="border-none shadow-lg bg-gradient-to-br from-white to-green-50">
|
||
<CardHeader>
|
||
<CardTitle className="text-lg font-bold">地区分布</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="h-[200px] flex items-center justify-center bg-gray-50 rounded-lg">
|
||
<p className="text-gray-500">地区分布图表将在此显示</p>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card className="border-none shadow-lg bg-gradient-to-br from-white to-blue-50">
|
||
<CardHeader>
|
||
<CardTitle className="text-lg font-bold">时间趋势</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="h-[200px] flex items-center justify-center bg-gray-50 rounded-lg">
|
||
<p className="text-gray-500">时间趋势图表将在此显示</p>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
</TabsContent>
|
||
</Tabs>
|
||
</DashboardShell>
|
||
)
|
||
}
|