"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import { Card } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { ChevronLeft, Smartphone, Users, Star, Clock, MessageSquare, Shield, Info, UserPlus, Search, Filter, Tag, ChevronRight, Loader2, } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Progress } from "@/components/ui/progress" import { Input } from "@/components/ui/input" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog" import { ScrollArea } from "@/components/ui/scroll-area" import { Tooltip as UITooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination" import { toast } from "@/components/ui/use-toast" import { fetchWechatAccountDetail, transformWechatAccountDetail } from "@/api/wechat-accounts" interface RestrictionRecord { id: string date: string reason: string recoveryTime: string type: "friend_limit" | "marketing" | "spam" | "other" } interface FriendTag { id: string name: string color: string } interface WechatFriend { id: string avatar: string nickname: string wechatId: string remark: string addTime: string lastInteraction: string tags: FriendTag[] region: string source: string notes: string } interface WechatAccountDetail { id: string avatar: string nickname: string wechatId: string deviceId: string deviceName: string friendCount: number todayAdded: number status: "normal" | "abnormal" lastActive: string messageCount: number activeRate: number // 新增和修改的字段 accountAge: { years: number months: number } totalChats: number chatFrequency: number // 每日平均聊天次数 restrictionRecords: RestrictionRecord[] isVerified: boolean firstMomentDate: string accountWeight: number weightFactors: { restrictionFactor: number verificationFactor: number ageFactor: number activityFactor: number } weeklyStats: { date: string friends: number messages: number }[] friends: WechatFriend[] } export default function WechatAccountDetailPage({ params }: { params: { id: string } }) { const router = useRouter() const [account, setAccount] = useState(null) const [showRestrictions, setShowRestrictions] = useState(false) const [showTransferConfirm, setShowTransferConfirm] = useState(false) const [showFriendDetail, setShowFriendDetail] = useState(false) const [selectedFriend, setSelectedFriend] = useState(null) const [searchQuery, setSearchQuery] = useState("") const [currentPage, setCurrentPage] = useState(1) const [activeTab, setActiveTab] = useState("overview") const friendsPerPage = 10 const [isLoading, setIsLoading] = useState(false) useEffect(() => { // 模拟API调用获取账号详情 const fetchAccount = async () => { try { setIsLoading(true) // 调用API获取微信账号详情 const response = await fetchWechatAccountDetail(params.id) if (response && response.code === 200) { // 转换数据格式 const transformedAccount = transformWechatAccountDetail(response) setAccount(transformedAccount) } else { toast({ title: "获取微信账号详情失败", description: response?.msg || "请稍后再试", variant: "destructive" }) // 获取失败时使用模拟数据 setAccount(generateMockAccountData()) } } catch (error) { console.error("获取微信账号详情失败:", error) toast({ title: "获取微信账号详情失败", description: "请检查网络连接或稍后再试", variant: "destructive" }) // 请求出错时使用模拟数据 setAccount(generateMockAccountData()) } finally { setIsLoading(false) } } fetchAccount() }, [params.id]) if (!account) { return
加载中...
} const getWeightColor = (weight: number) => { if (weight >= 80) return "text-green-600" if (weight >= 60) return "text-yellow-600" return "text-red-600" } const getWeightDescription = (weight: number) => { if (weight >= 80) return "账号状态良好" if (weight >= 60) return "账号状态一般" return "账号状态较差" } const calculateMaxDailyAdds = (weight: number) => { const baseLimit = 20 return Math.floor(baseLimit * (weight / 100)) } const getRestrictionTypeColor = (type: string) => { switch (type) { case "friend_limit": return "text-yellow-600" case "marketing": return "text-red-600" case "spam": return "text-orange-600" default: return "text-gray-600" } } const formatAccountAge = (age: { years: number; months: number }) => { if (age.years === 0) { return `${age.months}个月` } if (age.months === 0) { return `${age.years}年` } return `${age.years}年${age.months}个月` } const handleTransferFriends = () => { setShowTransferConfirm(true) } const confirmTransferFriends = () => { setShowTransferConfirm(false) // 跳转到新建计划的订单导入场景 router.push(`/scenarios/new?type=order&source=${account.wechatId}`) } const handleFriendClick = (friend: WechatFriend) => { setSelectedFriend(friend) setShowFriendDetail(true) } // 过滤好友 const filteredFriends = account.friends.filter( (friend) => friend.nickname.toLowerCase().includes(searchQuery.toLowerCase()) || friend.wechatId.toLowerCase().includes(searchQuery.toLowerCase()) || friend.remark.toLowerCase().includes(searchQuery.toLowerCase()) || friend.tags.some((tag) => tag.name.toLowerCase().includes(searchQuery.toLowerCase())), ) // 分页 const totalPages = Math.ceil(filteredFriends.length / friendsPerPage) const paginatedFriends = filteredFriends.slice((currentPage - 1) * friendsPerPage, currentPage * friendsPerPage) // 生成模拟账号数据(作为备用,服务器请求失败时使用) const generateMockAccountData = () => { // 生成随机标签 const generateRandomTags = (count: number) => { const tagPool = [ { name: "潜在客户", color: "bg-blue-100 text-blue-800" }, { name: "高意向", color: "bg-green-100 text-green-800" }, { name: "已成交", color: "bg-purple-100 text-purple-800" }, { name: "需跟进", color: "bg-yellow-100 text-yellow-800" }, { name: "活跃用户", color: "bg-indigo-100 text-indigo-800" }, { name: "沉默用户", color: "bg-gray-100 text-gray-800" }, { name: "企业客户", color: "bg-red-100 text-red-800" }, { name: "个人用户", color: "bg-pink-100 text-pink-800" }, { name: "新增好友", color: "bg-emerald-100 text-emerald-800" }, { name: "老客户", color: "bg-amber-100 text-amber-800" }, ] return Array.from({ length: Math.floor(Math.random() * count) + 1 }, () => { const randomTag = tagPool[Math.floor(Math.random() * tagPool.length)] return { id: `tag-${Math.random().toString(36).substring(2, 9)}`, name: randomTag.name, color: randomTag.color, } }) } // 生成随机好友 const friendCount = Math.floor(Math.random() * (300 - 150)) + 150 const generateFriends = (count: number) => { return Array.from({ length: count }, (_, i) => { const firstName = ["张", "王", "李", "赵", "陈", "刘", "杨", "黄", "周", "吴"][Math.floor(Math.random() * 10)] const secondName = ["小", "大", "明", "华", "强", "伟", "芳", "娜", "秀", "英"][ Math.floor(Math.random() * 10) ] const lastName = ["明", "华", "强", "伟", "芳", "娜", "秀", "英", "军", "杰"][Math.floor(Math.random() * 10)] const nickname = firstName + secondName + lastName // 生成随机的添加时间(过去1年内) const addDate = new Date() addDate.setDate(addDate.getDate() - Math.floor(Math.random() * 365)) // 生成随机的最后互动时间(过去30天内) const lastDate = new Date() lastDate.setDate(lastDate.getDate() - Math.floor(Math.random() * 30)) return { id: `friend-${i}`, avatar: `/placeholder.svg?height=40&width=40&text=${nickname[0]}`, nickname, wechatId: `wxid_${Math.random().toString(36).substring(2, 9)}`, remark: Math.random() > 0.5 ? `${nickname}(${["同事", "客户", "朋友", "同学"][Math.floor(Math.random() * 4)]})` : "", addTime: addDate.toISOString().split("T")[0], lastInteraction: lastDate.toISOString().split("T")[0], tags: generateRandomTags(3), region: ["广东", "北京", "上海", "浙江", "江苏", "四川", "湖北", "福建", "山东", "河南"][ Math.floor(Math.random() * 10) ], source: ["抖音", "小红书", "朋友介绍", "搜索添加", "群聊", "附近的人", "名片分享"][ Math.floor(Math.random() * 7) ], notes: Math.random() > 0.7 ? ["对产品很感兴趣", "需要进一步跟进", "已购买过产品", "价格敏感", "需要更多信息"][ Math.floor(Math.random() * 5) ] : "", } }) } const friends = generateFriends(friendCount) const mockAccount: WechatAccountDetail = { id: params.id, avatar: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/img_v3_02jn_e7fcc2a4-3560-478d-911a-4ccd69c6392g.jpg-a8zVtwxMuSrPWN9dfWH93EBY0yM3Dh.jpeg", nickname: "卡若-25vig", wechatId: `wxid_${Math.random().toString(36).substr(2, 8)}`, deviceId: "device-1", deviceName: "设备1", friendCount: friends.length, todayAdded: 12, status: "normal", lastActive: new Date().toLocaleString(), messageCount: 1234, activeRate: 87, accountAge: { years: 2, months: 8, }, totalChats: 15234, chatFrequency: 42, restrictionRecords: [ { id: "1", date: "2024-02-25", reason: "添加好友过于频繁", recoveryTime: "2024-02-26", type: "friend_limit", }, { id: "2", date: "2024-01-15", reason: "营销内容违规", recoveryTime: "2024-01-16", type: "marketing", }, ], isVerified: true, firstMomentDate: "2021-06-15", accountWeight: 85, weightFactors: { restrictionFactor: 0.8, verificationFactor: 1.0, ageFactor: 0.9, activityFactor: 0.85, }, weeklyStats: Array.from({ length: 7 }, (_, i) => ({ date: `Day ${i + 1}`, friends: Math.floor(Math.random() * 50) + 50, messages: Math.floor(Math.random() * 100) + 100, })), friends: friends, } return mockAccount } return ( {isLoading ? (
) : account ? (

账号详情

{account.nickname[0]} {account.isVerified && ( 已认证 )}

{account.nickname}

{account.status === "normal" ? "正常" : "异常"}

微信号:{account.wechatId}

账号概览 好友列表 ({account.friendCount}) {/* 账号基础信息 */}
账号年龄
{formatAccountAge(account.accountAge)}
注册时间:{account.firstMomentDate}
活跃程度
{account.chatFrequency}次/天
总聊天数:{account.totalChats.toLocaleString()}
{/* 账号权重评估 */}
账号权重评估
{account.accountWeight}

{getWeightDescription(account.accountWeight)}

账号年龄 {(account.weightFactors.ageFactor * 100).toFixed(0)}%
活跃度 {(account.weightFactors.activityFactor * 100).toFixed(0)}%
限制影响 {(account.weightFactors.restrictionFactor * 100).toFixed(0)}%
实名认证 {(account.weightFactors.verificationFactor * 100).toFixed(0)}%
{/* 添加好友统计 */}
添加好友统计

根据账号权重计算每日可添加好友数量

今日已添加 {account.todayAdded}
添加进度 {account.todayAdded}/{calculateMaxDailyAdds(account.accountWeight)}
根据当前账号权重({account.accountWeight}分),每日最多可添加{" "} {calculateMaxDailyAdds(account.accountWeight)}{" "} 个好友
{/* 限制记录 */}
限制记录
setShowRestrictions(true)}> 共 {account.restrictionRecords.length} 次
{account.restrictionRecords.slice(0, 2).map((record) => (
{record.reason} {record.date}
))}
{/* 搜索栏 */}
setSearchQuery(e.target.value)} className="pl-9" />
{/* 好友列表 */}
{paginatedFriends.length === 0 ? (
未找到匹配的好友
) : ( paginatedFriends.map((friend) => (
handleFriendClick(friend)} > {friend.nickname[0]}
{friend.nickname} {friend.remark && ({friend.remark})}
{friend.wechatId}
{friend.tags.slice(0, 3).map((tag) => ( {tag.name} ))} {friend.tags.length > 3 && ( +{friend.tags.length - 3} )}
)) )}
{/* 分页 */} {totalPages > 1 && ( { e.preventDefault() setCurrentPage((prev) => Math.max(1, prev - 1)) }} /> {Array.from({ length: Math.min(5, totalPages) }, (_, i) => { let pageNumber if (totalPages <= 5) { pageNumber = i + 1 } else if (currentPage <= 3) { pageNumber = i + 1 } else if (currentPage >= totalPages - 2) { pageNumber = totalPages - 4 + i } else { pageNumber = currentPage - 2 + i } return ( { e.preventDefault() setCurrentPage(pageNumber) }} > {pageNumber} ) })} { e.preventDefault() setCurrentPage((prev) => Math.min(totalPages, prev + 1)) }} /> )}
{/* 限制记录详情弹窗 */} 限制记录详情 每次限制恢复时间为24小时
{account.restrictionRecords.map((record) => (
{record.reason}
{record.date}
恢复时间:{record.recoveryTime}
))}
{/* 好友转移确认弹窗 */} 好友转移确认 即将导出该微信号的好友列表,用于创建新的获客计划
{account.nickname[0]}
{account.nickname}
{account.wechatId}

• 将导出该账号下的所有好友信息

• 好友信息将用于创建新的订单获客计划

• 导出过程中请勿关闭页面

{/* 好友详情弹窗 */} 好友详情 {selectedFriend && (
{selectedFriend.nickname[0]}
{selectedFriend.nickname}
{selectedFriend.wechatId}
{selectedFriend.remark && (
备注: {selectedFriend.remark}
)}
添加时间
{selectedFriend.addTime}
最近互动
{selectedFriend.lastInteraction}
地区
{selectedFriend.region}
来源
{selectedFriend.source}
标签
{selectedFriend.tags.map((tag) => ( {tag.name} ))} {selectedFriend.tags.length === 0 && 暂无标签}
{selectedFriend.notes && (
备注信息
{selectedFriend.notes}
)}
)}
) : (

未找到账号信息

)}
) }