refactor: overhaul UI for streamlined user experience
Redesign navigation, home overview, user portrait, and valuation pages with improved functionality and responsive design. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
276
components/user-portrait/tag-management.tsx
Normal file
276
components/user-portrait/tag-management.tsx
Normal file
@@ -0,0 +1,276 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { PlusCircle, Search, Tag, Edit, Trash2, Users } from "lucide-react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
|
||||
interface UserTag {
|
||||
id: string
|
||||
name: string
|
||||
category: string
|
||||
description: string
|
||||
userCount: number
|
||||
source: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export function TagManagement() {
|
||||
const [searchQuery, setSearchQuery] = useState("")
|
||||
const [selectedCategory, setSelectedCategory] = useState("all")
|
||||
const [selectedSource, setSelectedSource] = useState("all")
|
||||
|
||||
// 模拟数据
|
||||
const tags: UserTag[] = [
|
||||
{
|
||||
id: "1",
|
||||
name: "高价值客户",
|
||||
category: "价值分类",
|
||||
description: "消费金额高且频次高的用户",
|
||||
userCount: 2450,
|
||||
source: "系统生成",
|
||||
createdAt: new Date(2023, 5, 15),
|
||||
updatedAt: new Date(2023, 6, 20),
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "数据分析师",
|
||||
category: "职业角色",
|
||||
description: "从事数据分析工作的用户",
|
||||
userCount: 980,
|
||||
source: "流量词映射",
|
||||
createdAt: new Date(2023, 4, 10),
|
||||
updatedAt: new Date(2023, 6, 18),
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "营销决策者",
|
||||
category: "职业角色",
|
||||
description: "负责营销决策的管理人员",
|
||||
userCount: 645,
|
||||
source: "流量词映射",
|
||||
createdAt: new Date(2023, 3, 5),
|
||||
updatedAt: new Date(2023, 5, 25),
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "技术爱好者",
|
||||
category: "兴趣爱好",
|
||||
description: "对技术有浓厚兴趣的用户",
|
||||
userCount: 1520,
|
||||
source: "行为分析",
|
||||
createdAt: new Date(2023, 2, 20),
|
||||
updatedAt: new Date(2023, 6, 19),
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "活跃用户",
|
||||
category: "活跃度",
|
||||
description: "每周登录3次以上的用户",
|
||||
userCount: 8600,
|
||||
source: "系统生成",
|
||||
createdAt: new Date(2023, 1, 15),
|
||||
updatedAt: new Date(2023, 4, 10),
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
name: "上海市",
|
||||
category: "位置信息",
|
||||
description: "位于上海市的用户",
|
||||
userCount: 5200,
|
||||
source: "消费行为",
|
||||
createdAt: new Date(2023, 3, 10),
|
||||
updatedAt: new Date(2023, 6, 15),
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
name: "牛排",
|
||||
category: "菜品偏好",
|
||||
description: "喜欢牛排的用户",
|
||||
userCount: 3800,
|
||||
source: "消费行为",
|
||||
createdAt: new Date(2023, 4, 5),
|
||||
updatedAt: new Date(2023, 6, 12),
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
name: "晚餐",
|
||||
category: "消费时段",
|
||||
description: "晚餐时段消费的用户",
|
||||
userCount: 7500,
|
||||
source: "消费行为",
|
||||
createdAt: new Date(2023, 2, 15),
|
||||
updatedAt: new Date(2023, 5, 20),
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
name: "周末消费",
|
||||
category: "消费习惯",
|
||||
description: "周末消费的用户",
|
||||
userCount: 6200,
|
||||
source: "消费行为",
|
||||
createdAt: new Date(2023, 3, 20),
|
||||
updatedAt: new Date(2023, 6, 10),
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
name: "高端餐厅",
|
||||
category: "消费场所",
|
||||
description: "在高端餐厅消费的用户",
|
||||
userCount: 2900,
|
||||
source: "消费行为",
|
||||
createdAt: new Date(2023, 4, 25),
|
||||
updatedAt: new Date(2023, 6, 5),
|
||||
},
|
||||
]
|
||||
|
||||
// 过滤标签
|
||||
const filteredTags = tags.filter((tag) => {
|
||||
// 搜索过滤
|
||||
const searchMatch =
|
||||
tag.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
tag.category.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
tag.description.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
|
||||
// 分类过滤
|
||||
const categoryMatch = selectedCategory === "all" || tag.category === selectedCategory
|
||||
|
||||
// 来源过滤
|
||||
const sourceMatch = selectedSource === "all" || tag.source === selectedSource
|
||||
|
||||
return searchMatch && categoryMatch && sourceMatch
|
||||
})
|
||||
|
||||
const formatDate = (date: Date) => {
|
||||
return date.toLocaleDateString("zh-CN", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="border-none shadow-md overflow-hidden">
|
||||
<CardHeader className="bg-gradient-to-r from-green-50 to-teal-50 border-b">
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<CardTitle>用户标签管理</CardTitle>
|
||||
<CardDescription>管理系统中的用户标签</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-4">
|
||||
<div className="space-y-6">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-xl font-semibold">用户标签体系</h2>
|
||||
<Button>
|
||||
<PlusCircle className="mr-2 h-4 w-4" />
|
||||
创建新标签
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex space-x-2">
|
||||
<Select value={selectedCategory} onValueChange={setSelectedCategory}>
|
||||
<SelectTrigger className="w-[150px]">
|
||||
<SelectValue placeholder="标签分类" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">全部分类</SelectItem>
|
||||
<SelectItem value="价值分类">价值分类</SelectItem>
|
||||
<SelectItem value="职业角色">职业角色</SelectItem>
|
||||
<SelectItem value="兴趣爱好">兴趣爱好</SelectItem>
|
||||
<SelectItem value="活跃度">活跃度</SelectItem>
|
||||
<SelectItem value="位置信息">位置信息</SelectItem>
|
||||
<SelectItem value="菜品偏好">菜品偏好</SelectItem>
|
||||
<SelectItem value="消费时段">消费时段</SelectItem>
|
||||
<SelectItem value="消费习惯">消费习惯</SelectItem>
|
||||
<SelectItem value="消费场所">消费场所</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select value={selectedSource} onValueChange={setSelectedSource}>
|
||||
<SelectTrigger className="w-[150px]">
|
||||
<SelectValue placeholder="标签来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">全部来源</SelectItem>
|
||||
<SelectItem value="系统生成">系统生成</SelectItem>
|
||||
<SelectItem value="流量词映射">流量词映射</SelectItem>
|
||||
<SelectItem value="行为分析">行为分析</SelectItem>
|
||||
<SelectItem value="消费行为">消费行为</SelectItem>
|
||||
<SelectItem value="手动创建">手动创建</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="relative w-64">
|
||||
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="搜索标签..."
|
||||
className="pl-8"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>标签名称</TableHead>
|
||||
<TableHead>分类</TableHead>
|
||||
<TableHead>描述</TableHead>
|
||||
<TableHead>用户数量</TableHead>
|
||||
<TableHead>来源</TableHead>
|
||||
<TableHead>创建时间</TableHead>
|
||||
<TableHead>更新时间</TableHead>
|
||||
<TableHead className="text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredTags.map((tag) => (
|
||||
<TableRow key={tag.id}>
|
||||
<TableCell>
|
||||
<div className="flex items-center">
|
||||
<Tag className="h-4 w-4 mr-2 text-muted-foreground" />
|
||||
<span className="font-medium">{tag.name}</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">{tag.category}</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{tag.description}</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center">
|
||||
<Users className="h-4 w-4 mr-1 text-muted-foreground" />
|
||||
{tag.userCount.toLocaleString()}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{tag.source}</TableCell>
|
||||
<TableCell>{formatDate(tag.createdAt)}</TableCell>
|
||||
<TableCell>{formatDate(tag.updatedAt)}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end space-x-2">
|
||||
<Button variant="ghost" size="icon">
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" className="text-red-500">
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user