feat: 炫酷的登录页

This commit is contained in:
Blizzard
2026-04-28 16:43:34 +08:00
parent 3cade8e7ef
commit ccb36fa59c
34 changed files with 2390 additions and 253 deletions
+141
View File
@@ -0,0 +1,141 @@
import { useState } from 'react'
import { Plus, Search, Edit, Trash2, Gift, MoreHorizontal } from 'lucide-react'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Label } from '@/components/ui/label'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
import { Textarea } from '@/components/ui/textarea'
const mockItems = [
{ id: '1', name: '多肉植物盆栽', icon: '🪴', points: 500, stock: 50, sold: 23, category: '绿植', isActive: true, description: '精选多肉植物,含陶瓷花盆' },
{ id: '2', name: '园艺工具套装', icon: '🔧', points: 800, stock: 30, sold: 12, category: '工具', isActive: true, description: '包含铲子、剪刀、喷壶' },
{ id: '3', name: '植物生长灯', icon: '💡', points: 1200, stock: 20, sold: 8, category: '设备', isActive: true, description: 'LED全光谱补光灯' },
{ id: '4', name: '有机肥料包', icon: '🌿', points: 300, stock: 100, sold: 67, category: '肥料', isActive: true, description: '天然有机肥料 500g' },
{ id: '5', name: '花盆三件套', icon: '🏺', points: 600, stock: 0, sold: 45, category: '花盆', isActive: false, description: '陶瓷花盆 大中小三件套' },
{ id: '6', name: '种子礼盒', icon: '🌱', points: 200, stock: 200, sold: 156, category: '种子', isActive: true, description: '含向日葵、薄荷、薰衣草种子各一包' },
]
export default function ExchangeConfigPage() {
const [items] = useState(mockItems)
const [dialogOpen, setDialogOpen] = useState(false)
const [search, setSearch] = useState('')
const filtered = items.filter(i => !search || i.name.includes(search))
return (
<div className="space-y-6 animate-fadeIn">
<div>
<h1 className="text-2xl font-bold tracking-tight"></h1>
<p className="text-muted-foreground mt-1"></p>
</div>
<Card className="border-border/60 shadow-soft">
<CardHeader className="pb-3 border-b border-border/40">
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<CardTitle className="text-lg flex items-center gap-2">
<Gift className="h-5 w-5 text-primary" />
<Badge variant="secondary" className="text-xs">{filtered.length}</Badge>
</CardTitle>
<div className="flex items-center gap-3">
<div className="relative">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
<Input placeholder="搜索商品..." className="pl-9 w-48 h-9" value={search} onChange={e => setSearch(e.target.value)} />
</div>
<Button size="sm" onClick={() => setDialogOpen(true)} className="h-9 gap-1.5">
<Plus className="h-4 w-4" />
</Button>
</div>
</div>
</CardHeader>
<CardContent className="p-0">
<Table>
<TableHeader className="bg-muted/30">
<TableRow>
<TableHead className="pl-6 w-[60px]"></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead> / </TableHead>
<TableHead></TableHead>
<TableHead className="w-[60px]" />
</TableRow>
</TableHeader>
<TableBody>
{filtered.map(item => (
<TableRow key={item.id} className="group hover:bg-muted/20">
<TableCell className="pl-6 text-2xl">{item.icon}</TableCell>
<TableCell>
<div><span className="font-medium">{item.name}</span></div>
<div className="text-xs text-muted-foreground truncate max-w-[200px]">{item.description}</div>
</TableCell>
<TableCell><Badge variant="outline" className="bg-primary/5">{item.category}</Badge></TableCell>
<TableCell><span className="font-mono text-amber-600 font-semibold">{item.points}</span></TableCell>
<TableCell>
<span className={`font-mono text-sm ${item.stock === 0 ? 'text-red-500' : 'text-foreground'}`}>
{item.stock}
</span>
<span className="text-muted-foreground mx-1">/</span>
<span className="font-mono text-sm text-muted-foreground">{item.sold}</span>
</TableCell>
<TableCell>
{item.isActive
? <Badge className="bg-emerald-500/10 text-emerald-600 border-emerald-200 shadow-none"></Badge>
: <Badge variant="secondary" className="shadow-none"></Badge>}
</TableCell>
<TableCell>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" className="h-8 w-8 opacity-0 group-hover:opacity-100">
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem><Edit className="mr-2 h-4 w-4" /> </DropdownMenuItem>
<DropdownMenuItem className="text-red-500"><Trash2 className="mr-2 h-4 w-4" /> </DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription></DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label className="text-right"></Label>
<Input className="col-span-3" placeholder="如: 多肉植物盆栽" />
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label className="text-right"></Label>
<Input className="col-span-3" type="number" placeholder="500" />
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label className="text-right"></Label>
<Input className="col-span-3" type="number" placeholder="100" />
</div>
<div className="grid grid-cols-4 items-start gap-4">
<Label className="text-right pt-2"></Label>
<Textarea className="col-span-3" placeholder="商品描述..." rows={3} />
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setDialogOpen(false)}></Button>
<Button onClick={() => setDialogOpen(false)}></Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
)
}