私域操盘手 - 修复流量池页面点击”全部来源“和全部状态的select框,页面被压缩的问题
This commit is contained in:
@@ -85,7 +85,7 @@ export default function TrafficPoolPage() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 检查是否有来源参数
|
// 检查是否有来源参数
|
||||||
const sourceParam = searchParams.get("source")
|
const sourceParam = searchParams?.get("source")
|
||||||
if (sourceParam) {
|
if (sourceParam) {
|
||||||
params.append("wechatSource", sourceParam)
|
params.append("wechatSource", sourceParam)
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ export default function TrafficPoolPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 bg-white min-h-screen">
|
<div className="flex-1 bg-white min-h-screen flex flex-col">
|
||||||
<header className="sticky top-0 z-10 bg-white border-b">
|
<header className="sticky top-0 z-10 bg-white border-b">
|
||||||
<div className="flex items-center justify-between p-4">
|
<div className="flex items-center justify-between p-4">
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
@@ -177,195 +177,197 @@ export default function TrafficPoolPage() {
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="p-4 space-y-6">
|
<div className="flex-1 overflow-y-auto">
|
||||||
{/* 搜索和筛选区域 */}
|
<div className="p-4 space-y-6">
|
||||||
<div className="flex items-center space-x-2">
|
{/* 搜索和筛选区域 */}
|
||||||
<div className="relative flex-1">
|
<div className="flex items-center space-x-2">
|
||||||
<Search className="absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
|
<div className="relative flex-1">
|
||||||
<Input
|
<Search className="absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
|
||||||
placeholder="搜索用户"
|
<Input
|
||||||
value={searchQuery}
|
placeholder="搜索用户"
|
||||||
onChange={(e) => {
|
value={searchQuery}
|
||||||
setSearchQuery(e.target.value)
|
onChange={(e) => {
|
||||||
|
setSearchQuery(e.target.value)
|
||||||
|
setCurrentPage(1)
|
||||||
|
}}
|
||||||
|
className="pl-9"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<Filter className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 统计卡片 */}
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<Card className="p-4">
|
||||||
|
<div className="text-sm text-gray-500">流量池总数</div>
|
||||||
|
<div className="text-2xl font-bold text-blue-600">{stats.total}</div>
|
||||||
|
</Card>
|
||||||
|
<Card className="p-4">
|
||||||
|
<div className="text-sm text-gray-500">今日新增</div>
|
||||||
|
<div className="text-2xl font-bold text-green-600">{stats.todayNew}</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 分类标签页 */}
|
||||||
|
<Tabs
|
||||||
|
defaultValue="potential"
|
||||||
|
value={activeCategory}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setActiveCategory(value)
|
||||||
|
setCurrentPage(1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TabsList className="grid w-full grid-cols-2">
|
||||||
|
<TabsTrigger value="potential">潜在客户</TabsTrigger>
|
||||||
|
<TabsTrigger value="customer">已转化</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
{/* 筛选器 */}
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<Select
|
||||||
|
value={sourceFilter}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setSourceFilter(value)
|
||||||
setCurrentPage(1)
|
setCurrentPage(1)
|
||||||
}}
|
}}
|
||||||
className="pl-9"
|
>
|
||||||
/>
|
<SelectTrigger className="w-[120px]">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
value={statusFilter}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setStatusFilter(value)
|
||||||
|
setCurrentPage(1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[120px]">
|
||||||
|
<SelectValue placeholder="状态" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="all">全部状态</SelectItem>
|
||||||
|
<SelectItem value="pending">待处理</SelectItem>
|
||||||
|
<SelectItem value="added">已添加</SelectItem>
|
||||||
|
<SelectItem value="failed">已失败</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="outline" size="icon">
|
|
||||||
<Filter className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 统计卡片 */}
|
{/* 用户列表 */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="space-y-2">
|
||||||
<Card className="p-4">
|
{loading ? (
|
||||||
<div className="text-sm text-gray-500">流量池总数</div>
|
<div className="flex flex-col items-center justify-center py-12">
|
||||||
<div className="text-2xl font-bold text-blue-600">{stats.total}</div>
|
<RefreshCw className="h-8 w-8 text-blue-500 animate-spin mb-4" />
|
||||||
</Card>
|
<div className="text-gray-500">加载中...</div>
|
||||||
<Card className="p-4">
|
</div>
|
||||||
<div className="text-sm text-gray-500">今日新增</div>
|
) : users.length === 0 ? (
|
||||||
<div className="text-2xl font-bold text-green-600">{stats.todayNew}</div>
|
<div className="text-center py-12 bg-gray-50 rounded-lg">
|
||||||
</Card>
|
<div className="text-gray-500">暂无数据</div>
|
||||||
</div>
|
<Button variant="outline" className="mt-4" onClick={fetchUsers}>
|
||||||
|
刷新
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
users.map((user) => (
|
||||||
|
<Card
|
||||||
|
key={user.id}
|
||||||
|
className="p-3 cursor-pointer hover:shadow-md transition-shadow"
|
||||||
|
onClick={() => handleUserClick(user)}
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<img src={user.avatar || "/placeholder.svg"} alt="" className="w-10 h-10 rounded-full bg-gray-100" />
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="font-medium truncate">{user.nickname}</div>
|
||||||
|
<div
|
||||||
|
className={`text-xs px-2 py-1 rounded-full ${
|
||||||
|
user.status === "added"
|
||||||
|
? "bg-green-100 text-green-800"
|
||||||
|
: user.status === "pending"
|
||||||
|
? "bg-yellow-100 text-yellow-800"
|
||||||
|
: "bg-red-100 text-red-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{user.status === "added" ? "已添加" : user.status === "pending" ? "待处理" : "已失败"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-500">微信号: {user.wechatId}</div>
|
||||||
|
<div className="text-sm text-gray-500">来源: {user.source}</div>
|
||||||
|
<div className="text-sm text-gray-500">添加时间: {new Date(user.addTime).toLocaleString()}</div>
|
||||||
|
|
||||||
{/* 分类标签页 - 移除了"全部"选项 */}
|
{/* 标签展示 */}
|
||||||
<Tabs
|
<div className="flex flex-wrap gap-1 mt-2">
|
||||||
defaultValue="potential"
|
{user.tags.slice(0, 2).map((tag) => (
|
||||||
value={activeCategory}
|
<span key={tag.id} className={`text-xs px-2 py-0.5 rounded-full ${tag.color}`}>
|
||||||
onValueChange={(value) => {
|
{tag.name}
|
||||||
setActiveCategory(value)
|
</span>
|
||||||
setCurrentPage(1)
|
))}
|
||||||
}}
|
{user.tags.length > 2 && (
|
||||||
>
|
<span className="text-xs px-2 py-0.5 rounded-full bg-gray-100 text-gray-800">
|
||||||
<TabsList className="grid w-full grid-cols-2">
|
+{user.tags.length - 2}
|
||||||
<TabsTrigger value="potential">潜在客户</TabsTrigger>
|
</span>
|
||||||
<TabsTrigger value="customer">已转化</TabsTrigger>
|
)}
|
||||||
</TabsList>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
{/* 筛选器 */}
|
|
||||||
<div className="flex space-x-2">
|
|
||||||
<Select
|
|
||||||
value={sourceFilter}
|
|
||||||
onValueChange={(value) => {
|
|
||||||
setSourceFilter(value)
|
|
||||||
setCurrentPage(1)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-[120px]">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
value={statusFilter}
|
|
||||||
onValueChange={(value) => {
|
|
||||||
setStatusFilter(value)
|
|
||||||
setCurrentPage(1)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-[120px]">
|
|
||||||
<SelectValue placeholder="状态" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="all">全部状态</SelectItem>
|
|
||||||
<SelectItem value="pending">待处理</SelectItem>
|
|
||||||
<SelectItem value="added">已添加</SelectItem>
|
|
||||||
<SelectItem value="failed">已失败</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 用户列表 - 改进加载状态显示 */}
|
|
||||||
<div className="space-y-2">
|
|
||||||
{loading ? (
|
|
||||||
<div className="flex flex-col items-center justify-center py-12">
|
|
||||||
<RefreshCw className="h-8 w-8 text-blue-500 animate-spin mb-4" />
|
|
||||||
<div className="text-gray-500">加载中...</div>
|
|
||||||
</div>
|
|
||||||
) : users.length === 0 ? (
|
|
||||||
<div className="text-center py-12 bg-gray-50 rounded-lg">
|
|
||||||
<div className="text-gray-500">暂无数据</div>
|
|
||||||
<Button variant="outline" className="mt-4" onClick={fetchUsers}>
|
|
||||||
刷新
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
users.map((user) => (
|
|
||||||
<Card
|
|
||||||
key={user.id}
|
|
||||||
className="p-3 cursor-pointer hover:shadow-md transition-shadow"
|
|
||||||
onClick={() => handleUserClick(user)}
|
|
||||||
>
|
|
||||||
<div className="flex items-center space-x-3">
|
|
||||||
<img src={user.avatar || "/placeholder.svg"} alt="" className="w-10 h-10 rounded-full bg-gray-100" />
|
|
||||||
<div className="flex-1 min-w-0">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="font-medium truncate">{user.nickname}</div>
|
|
||||||
<div
|
|
||||||
className={`text-xs px-2 py-1 rounded-full ${
|
|
||||||
user.status === "added"
|
|
||||||
? "bg-green-100 text-green-800"
|
|
||||||
: user.status === "pending"
|
|
||||||
? "bg-yellow-100 text-yellow-800"
|
|
||||||
: "bg-red-100 text-red-800"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{user.status === "added" ? "已添加" : user.status === "pending" ? "待处理" : "已失败"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-500">微信号: {user.wechatId}</div>
|
|
||||||
<div className="text-sm text-gray-500">来源: {user.source}</div>
|
|
||||||
<div className="text-sm text-gray-500">添加时间: {new Date(user.addTime).toLocaleString()}</div>
|
|
||||||
|
|
||||||
{/* 标签展示 */}
|
|
||||||
<div className="flex flex-wrap gap-1 mt-2">
|
|
||||||
{user.tags.slice(0, 2).map((tag) => (
|
|
||||||
<span key={tag.id} className={`text-xs px-2 py-0.5 rounded-full ${tag.color}`}>
|
|
||||||
{tag.name}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
{user.tags.length > 2 && (
|
|
||||||
<span className="text-xs px-2 py-0.5 rounded-full bg-gray-100 text-gray-800">
|
|
||||||
+{user.tags.length - 2}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
</Card>
|
))
|
||||||
))
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 分页 */}
|
{/* 分页 */}
|
||||||
{!loading && users.length > 0 && (
|
{!loading && users.length > 0 && (
|
||||||
<Pagination>
|
<Pagination>
|
||||||
<PaginationContent>
|
<PaginationContent>
|
||||||
<PaginationItem>
|
<PaginationItem>
|
||||||
<PaginationPrevious
|
<PaginationPrevious
|
||||||
href="#"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault()
|
|
||||||
setCurrentPage((prev) => Math.max(1, prev - 1))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</PaginationItem>
|
|
||||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
|
||||||
<PaginationItem key={page}>
|
|
||||||
<PaginationLink
|
|
||||||
href="#"
|
href="#"
|
||||||
isActive={currentPage === page}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setCurrentPage(page)
|
setCurrentPage((prev) => Math.max(1, prev - 1))
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
{page}
|
|
||||||
</PaginationLink>
|
|
||||||
</PaginationItem>
|
</PaginationItem>
|
||||||
))}
|
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||||
<PaginationItem>
|
<PaginationItem key={page}>
|
||||||
<PaginationNext
|
<PaginationLink
|
||||||
href="#"
|
href="#"
|
||||||
onClick={(e) => {
|
isActive={currentPage === page}
|
||||||
e.preventDefault()
|
onClick={(e) => {
|
||||||
setCurrentPage((prev) => Math.min(totalPages, prev + 1))
|
e.preventDefault()
|
||||||
}}
|
setCurrentPage(page)
|
||||||
/>
|
}}
|
||||||
</PaginationItem>
|
>
|
||||||
</PaginationContent>
|
{page}
|
||||||
</Pagination>
|
</PaginationLink>
|
||||||
)}
|
</PaginationItem>
|
||||||
|
))}
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationNext
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setCurrentPage((prev) => Math.min(totalPages, prev + 1))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PaginationItem>
|
||||||
|
</PaginationContent>
|
||||||
|
</Pagination>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 用户详情弹窗 */}
|
{/* 用户详情弹窗 */}
|
||||||
|
|||||||
@@ -398,17 +398,17 @@ export default function WechatAccountDetailPage() {
|
|||||||
setIsFetchingFriends(true);
|
setIsFetchingFriends(true);
|
||||||
setHasFriendLoadError(false);
|
setHasFriendLoadError(false);
|
||||||
|
|
||||||
const response = await api.get<ApiResponse<FriendsResponse>>(`/v1/wechats/${id}/friends?page=${page}&limit=30${searchQuery ? `&search=${encodeURIComponent(searchQuery)}` : ''}`, true);
|
const data = await api.get<ApiResponse<FriendsResponse>>(`/v1/wechats/${id}/friends?page=${page}&limit=30`, true);
|
||||||
|
|
||||||
if (response && response.code === 200 && response.data) {
|
if (data && data.code === 200) {
|
||||||
// 更新总数计数
|
// 更新总数计数
|
||||||
if (isNewSearch || friendsTotal === 0) {
|
if (isNewSearch || friendsTotal === 0) {
|
||||||
setFriendsTotal(response.data.total || 0);
|
setFriendsTotal(data.data.total || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newFriends = response.data.list.map((friend) => ({
|
const newFriends = data.data.list.map((friend) => ({
|
||||||
id: friend.id.toString(),
|
id: friend.id.toString(),
|
||||||
avatar: friend.avatar || '/placeholder.svg',
|
avatar: friend.avatar,
|
||||||
nickname: friend.nickname,
|
nickname: friend.nickname,
|
||||||
wechatId: friend.wechatId,
|
wechatId: friend.wechatId,
|
||||||
remark: friend.memo || '',
|
remark: friend.memo || '',
|
||||||
@@ -433,12 +433,13 @@ export default function WechatAccountDetailPage() {
|
|||||||
|
|
||||||
setFriendsPage(page);
|
setFriendsPage(page);
|
||||||
// 判断是否还有更多数据
|
// 判断是否还有更多数据
|
||||||
setHasMoreFriends(page * 30 < response.data.total);
|
setHasMoreFriends(page * 30 < data.data.total);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setHasFriendLoadError(true);
|
setHasFriendLoadError(true);
|
||||||
toast({
|
toast({
|
||||||
title: "获取好友列表失败",
|
title: "获取好友列表失败",
|
||||||
description: response?.msg || "请稍后再试",
|
description: data?.msg || "请稍后再试",
|
||||||
variant: "destructive"
|
variant: "destructive"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -453,7 +454,7 @@ export default function WechatAccountDetailPage() {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsFetchingFriends(false);
|
setIsFetchingFriends(false);
|
||||||
}
|
}
|
||||||
}, [account, id, friendsTotal, searchQuery]);
|
}, [account, id, friendsTotal]);
|
||||||
|
|
||||||
// 处理搜索
|
// 处理搜索
|
||||||
const handleSearch = useCallback(() => {
|
const handleSearch = useCallback(() => {
|
||||||
@@ -528,21 +529,21 @@ export default function WechatAccountDetailPage() {
|
|||||||
const response = await fetchWechatAccountSummary(id);
|
const response = await fetchWechatAccountSummary(id);
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
setAccountSummary(response.data);
|
setAccountSummary(response.data);
|
||||||
} else {
|
} else {
|
||||||
toast({
|
toast({
|
||||||
title: "获取账号概览失败",
|
title: "获取账号概览失败",
|
||||||
description: response.msg || "请稍后再试",
|
description: response.msg || "请稍后再试",
|
||||||
variant: "destructive"
|
variant: "destructive"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取账号概览失败:", error);
|
console.error("获取账号概览失败:", error);
|
||||||
toast({
|
toast({
|
||||||
title: "获取账号概览失败",
|
title: "获取账号概览失败",
|
||||||
description: "请检查网络连接或稍后再试",
|
description: "请检查网络连接或稍后再试",
|
||||||
variant: "destructive"
|
variant: "destructive"
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [id]);
|
}, [id]);
|
||||||
@@ -726,9 +727,9 @@ export default function WechatAccountDetailPage() {
|
|||||||
<Tabs value={activeTab} onValueChange={handleTabChange} className="w-full">
|
<Tabs value={activeTab} onValueChange={handleTabChange} className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2">
|
<TabsList className="grid w-full grid-cols-2">
|
||||||
<TabsTrigger value="overview">账号概览</TabsTrigger>
|
<TabsTrigger value="overview">账号概览</TabsTrigger>
|
||||||
<TabsTrigger value="friends">
|
<TabsTrigger value="friends">
|
||||||
好友列表{activeTab === "friends" && friendsTotal > 0 ? ` (${friendsTotal})` : ''}
|
好友列表{activeTab === "friends" && friendsTotal > 0 ? ` (${friendsTotal})` : ''}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="space-y-4 mt-4">
|
<TabsContent value="overview" className="space-y-4 mt-4">
|
||||||
@@ -775,33 +776,33 @@ export default function WechatAccountDetailPage() {
|
|||||||
{accountSummary && (
|
{accountSummary && (
|
||||||
<div className={`flex items-center space-x-2 ${getWeightColor(accountSummary.accountWeight.scope)}`}>
|
<div className={`flex items-center space-x-2 ${getWeightColor(accountSummary.accountWeight.scope)}`}>
|
||||||
<span className="text-2xl font-bold">{accountSummary.accountWeight.scope}</span>
|
<span className="text-2xl font-bold">{accountSummary.accountWeight.scope}</span>
|
||||||
<span className="text-sm">分</span>
|
<span className="text-sm">分</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{accountSummary && (
|
{accountSummary && (
|
||||||
<>
|
<>
|
||||||
<p className="text-sm text-gray-500 mb-4">{getWeightDescription(accountSummary.accountWeight.scope)}</p>
|
<p className="text-sm text-gray-500 mb-4">{getWeightDescription(accountSummary.accountWeight.scope)}</p>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<span className="flex-shrink-0 w-16 text-sm">账号年龄</span>
|
<span className="flex-shrink-0 w-16 text-sm">账号年龄</span>
|
||||||
<div className="flex-1 mx-4">
|
<div className="flex-1 mx-4">
|
||||||
<Progress value={accountSummary.accountWeight.ageWeight} className="h-2" />
|
<Progress value={accountSummary.accountWeight.ageWeight} className="h-2" />
|
||||||
</div>
|
</div>
|
||||||
<span className="flex-shrink-0 w-12 text-sm text-right">{accountSummary.accountWeight.ageWeight}%</span>
|
<span className="flex-shrink-0 w-12 text-sm text-right">{accountSummary.accountWeight.ageWeight}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<span className="flex-shrink-0 w-16 text-sm">活跃度</span>
|
<span className="flex-shrink-0 w-16 text-sm">活跃度</span>
|
||||||
<div className="flex-1 mx-4">
|
<div className="flex-1 mx-4">
|
||||||
<Progress value={accountSummary.accountWeight.activityWeigth} className="h-2" />
|
<Progress value={accountSummary.accountWeight.activityWeigth} className="h-2" />
|
||||||
</div>
|
</div>
|
||||||
<span className="flex-shrink-0 w-12 text-sm text-right">{accountSummary.accountWeight.activityWeigth}%</span>
|
<span className="flex-shrink-0 w-12 text-sm text-right">{accountSummary.accountWeight.activityWeigth}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<span className="flex-shrink-0 w-16 text-sm">限制影响</span>
|
<span className="flex-shrink-0 w-16 text-sm">限制影响</span>
|
||||||
<div className="flex-1 mx-4">
|
<div className="flex-1 mx-4">
|
||||||
<Progress value={accountSummary.accountWeight.restrictWeight} className="h-2" />
|
<Progress value={accountSummary.accountWeight.restrictWeight} className="h-2" />
|
||||||
</div>
|
</div>
|
||||||
<span className="flex-shrink-0 w-12 text-sm text-right">{accountSummary.accountWeight.restrictWeight}%</span>
|
<span className="flex-shrink-0 w-12 text-sm text-right">{accountSummary.accountWeight.restrictWeight}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@@ -833,29 +834,29 @@ export default function WechatAccountDetailPage() {
|
|||||||
</UITooltip>
|
</UITooltip>
|
||||||
</div>
|
</div>
|
||||||
{accountSummary && (
|
{accountSummary && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className="text-sm text-gray-500">今日已添加</span>
|
<span className="text-sm text-gray-500">今日已添加</span>
|
||||||
<span className="text-xl font-bold text-blue-600">{accountSummary.statistics.todayAdded}</span>
|
<span className="text-xl font-bold text-blue-600">{accountSummary.statistics.todayAdded}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between text-sm mb-2">
|
<div className="flex justify-between text-sm mb-2">
|
||||||
<span className="text-gray-500">添加进度</span>
|
<span className="text-gray-500">添加进度</span>
|
||||||
<span>
|
<span>
|
||||||
{accountSummary.statistics.todayAdded}/{accountSummary.statistics.addLimit}
|
{accountSummary.statistics.todayAdded}/{accountSummary.statistics.addLimit}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
|
||||||
<Progress
|
|
||||||
value={(accountSummary.statistics.todayAdded / accountSummary.statistics.addLimit) * 100}
|
|
||||||
className="h-2"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-500">
|
<Progress
|
||||||
|
value={(accountSummary.statistics.todayAdded / accountSummary.statistics.addLimit) * 100}
|
||||||
|
className="h-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-500">
|
||||||
根据当前账号权重({accountSummary.accountWeight.scope}分),每日最多可添加{" "}
|
根据当前账号权重({accountSummary.accountWeight.scope}分),每日最多可添加{" "}
|
||||||
<span className="font-medium text-blue-600">{accountSummary.statistics.addLimit}</span>{" "}
|
<span className="font-medium text-blue-600">{accountSummary.statistics.addLimit}</span>{" "}
|
||||||
个好友
|
个好友
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
@@ -867,24 +868,24 @@ export default function WechatAccountDetailPage() {
|
|||||||
<span className="font-medium">限制记录</span>
|
<span className="font-medium">限制记录</span>
|
||||||
</div>
|
</div>
|
||||||
{accountSummary && (
|
{accountSummary && (
|
||||||
<Badge variant="outline" className="cursor-pointer" onClick={() => setShowRestrictions(true)}>
|
<Badge variant="outline" className="cursor-pointer" onClick={() => setShowRestrictions(true)}>
|
||||||
共 {accountSummary.restrictions.length} 次
|
共 {accountSummary.restrictions.length} 次
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{accountSummary && (
|
{accountSummary && (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{accountSummary.restrictions.slice(0, 2).map((record) => (
|
{accountSummary.restrictions.slice(0, 2).map((record) => (
|
||||||
<div key={record.id} className="text-sm">
|
<div key={record.id} className="text-sm">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className={`${getRestrictionLevelColor(record.level)}`}>
|
<span className={`${getRestrictionLevelColor(record.level)}`}>
|
||||||
{record.reason}
|
{record.reason}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-gray-500">{formatDateTime(record.date)}</span>
|
<span className="text-gray-500">{formatDateTime(record.date)}</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
</div>
|
||||||
</div>
|
))}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
@@ -1010,7 +1011,7 @@ export default function WechatAccountDetailPage() {
|
|||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div className={`text-sm ${getRestrictionLevelColor(record.level)}`}>
|
<div className={`text-sm ${getRestrictionLevelColor(record.level)}`}>
|
||||||
{record.reason}
|
{record.reason}
|
||||||
</div>
|
</div>
|
||||||
<Badge variant="outline">{formatDateTime(record.date)}</Badge>
|
<Badge variant="outline">{formatDateTime(record.date)}</Badge>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-500 mt-1">恢复时间:{formatDateTime(record.date)}</div>
|
<div className="text-sm text-gray-500 mt-1">恢复时间:{formatDateTime(record.date)}</div>
|
||||||
@@ -1186,7 +1187,7 @@ export default function WechatAccountDetailPage() {
|
|||||||
标签
|
标签
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{selectedFriend.tags.map((tag: FriendTag) => (
|
{selectedFriend.tags.map((tag: FriendTag) => (
|
||||||
<span key={tag.id} className={`text-sm px-2 py-1 rounded-full ${tag.color}`}>
|
<span key={tag.id} className={`text-sm px-2 py-1 rounded-full ${tag.color}`}>
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user