import React, { useState, useEffect, useRef, useCallback } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import PageHeader from '@/components/PageHeader'; import { ChevronLeft, Smartphone, Users, Star, Clock, MessageSquare, Shield, Info, UserPlus, Search, ChevronRight, Loader2 } from 'lucide-react'; import { useWechatAccount } from '@/contexts/WechatAccountContext'; import { fetchWechatAccountSummary, fetchWechatFriends, fetchWechatFriendDetail } from '@/api/wechat-accounts'; import { useToast } from '@/components/ui/toast'; import Layout from '@/components/Layout'; import '@/components/Layout.css'; interface WechatAccountSummary { accountAge: string; activityLevel: { allTimes: number; dayTimes: number; }; accountWeight: { scope: number; ageWeight: number; activityWeigth: number; restrictWeight: number; realNameWeight: number; }; statistics: { todayAdded: number; addLimit: number; }; restrictions: { id: number; level: string; reason: string; date: string; }[]; } interface Friend { id: string; avatar: string; nickname: string; wechatId: string; remark: string; addTime: string; lastInteraction: string; tags: Array<{ id: string; name: string; color: string; }>; region: string; source: string; notes: string; } interface WechatFriendDetail { id: number; avatar: string; nickname: string; region: string; wechatId: string; addDate: string; tags: string[]; memo: string; source: string; } export default function WechatAccountDetail() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { toast } = useToast(); const { currentAccount, clearCurrentAccount } = useWechatAccount(); const [accountSummary, setAccountSummary] = useState(null); const [showRestrictions, setShowRestrictions] = useState(false); const [showTransferConfirm, setShowTransferConfirm] = useState(false); const [showFriendDetail, setShowFriendDetail] = useState(false); const [selectedFriend, setSelectedFriend] = useState(null); const [friendDetail, setFriendDetail] = useState(null); const [isLoadingFriendDetail, setIsLoadingFriendDetail] = useState(false); const [friendDetailError, setFriendDetailError] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const [activeTab, setActiveTab] = useState("overview"); const [isLoading, setIsLoading] = useState(false); // 好友列表相关状态 const [friends, setFriends] = useState([]); const [friendsPage, setFriendsPage] = useState(1); const [friendsTotal, setFriendsTotal] = useState(0); const [hasMoreFriends, setHasMoreFriends] = useState(true); const [isFetchingFriends, setIsFetchingFriends] = useState(false); const [hasFriendLoadError, setHasFriendLoadError] = useState(false); const [isFriendsEmpty, setIsFriendsEmpty] = useState(false); const friendsObserver = useRef(null); const friendsLoadingRef = useRef(null); // 如果没有账号数据,返回上一页 useEffect(() => { if (!currentAccount) { toast({ title: "数据错误", description: "未找到账号信息,请重新选择", variant: "destructive" }); navigate('/wechat-accounts'); return; } }, [currentAccount, navigate, toast]); // 获取账号概览信息 const fetchAccountSummary = useCallback(async () => { if (!id) return; try { setIsLoading(true); const response = await fetchWechatAccountSummary(id); if (response && response.code === 200 && response.data) { setAccountSummary(response.data); } else { toast({ title: "获取账号概览失败", description: response?.msg || "请稍后重试", variant: "destructive" }); } } catch (error) { console.error("获取账号概览失败:", error); toast({ title: "获取账号概览失败", description: "请检查网络连接后重试", variant: "destructive" }); } finally { setIsLoading(false); } }, [id, toast]); // 获取好友列表 const fetchFriends = useCallback(async (page: number = 1, isNewSearch: boolean = false) => { console.log('fetchFriends called:', { page, isNewSearch, isFetchingFriends, id, searchQuery }); if (!id || isFetchingFriends) { console.log('fetchFriends early return:', { id, isFetchingFriends }); return; } try { setIsFetchingFriends(true); setHasFriendLoadError(false); console.log('Making API request for friends:', { id, page, searchQuery }); const response = await fetchWechatFriends(id, page, 20, searchQuery); console.log('API response:', response); if (response && response.code === 200 && response.data) { const newFriends = response.data.list.map((friend: any) => ({ id: friend.id.toString(), avatar: friend.avatar || "/placeholder.svg", nickname: friend.nickname || "未知用户", wechatId: friend.wechatId || "", remark: friend.memo || "", addTime: friend.createTime || new Date().toISOString().split('T')[0], lastInteraction: friend.lastInteraction || new Date().toISOString().split('T')[0], tags: friend.tags ? friend.tags.map((tag: string, index: number) => ({ id: `tag-${index}`, name: tag, color: getRandomTagColor() })) : [], region: friend.region || "未知", source: friend.source || "未知", notes: friend.notes || "" })); console.log('Processed friends:', { newFriendsCount: newFriends.length, isNewSearch }); if (isNewSearch) { setFriends(newFriends); // 如果是新搜索且数据为空,设置空状态 if (newFriends.length === 0) { console.log('Setting empty state for new search'); setIsFriendsEmpty(true); setHasMoreFriends(false); } else { console.log('Setting normal state for new search'); setIsFriendsEmpty(false); setHasMoreFriends(newFriends.length === 20); } } else { setFriends(prev => [...prev, ...newFriends]); setHasMoreFriends(newFriends.length === 20); } setFriendsTotal(response.data.total); setFriendsPage(page); } else { console.log('API response error:', response); setHasFriendLoadError(true); if (isNewSearch) { setFriends([]); setIsFriendsEmpty(true); setHasMoreFriends(false); } toast({ title: "获取好友列表失败", description: response?.msg || "请稍后重试", variant: "destructive" }); } } catch (error) { console.error("获取好友列表失败:", error); setHasFriendLoadError(true); if (isNewSearch) { setFriends([]); setIsFriendsEmpty(true); setHasMoreFriends(false); } toast({ title: "获取好友列表失败", description: "请检查网络连接后重试", variant: "destructive" }); } finally { console.log('Setting isFetchingFriends to false'); setIsFetchingFriends(false); } }, [id, searchQuery, toast]); // 初始化数据 useEffect(() => { if (id) { fetchAccountSummary(); if (activeTab === "friends") { fetchFriends(1, true); } } }, [id, fetchAccountSummary]); // 监听标签切换 useEffect(() => { if (activeTab === "friends" && id) { // 重置空状态,允许重新加载 setIsFriendsEmpty(false); setHasFriendLoadError(false); fetchFriends(1, true); } }, [activeTab, id, fetchFriends]); // 无限滚动加载好友 useEffect(() => { if (!friendsLoadingRef.current || !hasMoreFriends || isFetchingFriends || isFriendsEmpty) return; friendsObserver.current = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting && hasMoreFriends && !isFetchingFriends && !isFriendsEmpty) { fetchFriends(friendsPage + 1, false); } }, { threshold: 0.1 } ); friendsObserver.current.observe(friendsLoadingRef.current); return () => { if (friendsObserver.current) { friendsObserver.current.disconnect(); } }; }, [hasMoreFriends, isFetchingFriends, friendsPage, fetchFriends, isFriendsEmpty]); // 工具函数 const getRandomTagColor = (): string => { const colors = [ "bg-blue-100 text-blue-800", "bg-green-100 text-green-800", "bg-red-100 text-red-800", "bg-pink-100 text-pink-800", "bg-emerald-100 text-emerald-800", "bg-amber-100 text-amber-800", ]; return colors[Math.floor(Math.random() * colors.length)]; }; const calculateAccountAge = (registerTime: string) => { const registerDate = new Date(registerTime); const now = new Date(); const diffTime = Math.abs(now.getTime() - registerDate.getTime()); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); const years = Math.floor(diffDays / 365); const months = Math.floor((diffDays % 365) / 30); return { years, months }; }; const formatAccountAge = (age: { years: number; months: number }) => { if (age.years > 0) { return `${age.years}年${age.months}个月`; } return `${age.months}个月`; }; 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 handleTransferFriends = () => { setShowTransferConfirm(true); }; const confirmTransferFriends = () => { toast({ title: "好友转移计划已创建", description: "请在场景获客中查看详情", }); setShowTransferConfirm(false); navigate("/scenarios"); }; const handleBack = () => { clearCurrentAccount(); navigate('/wechat-accounts'); }; const handleFriendClick = async (friend: Friend) => { setSelectedFriend(friend); setShowFriendDetail(true); setIsLoadingFriendDetail(true); setFriendDetailError(null); try { const response = await fetchWechatFriendDetail(friend.id); if (response && response.code === 200 && response.data) { setFriendDetail(response.data); } else { setFriendDetailError(response?.msg || "获取好友详情失败"); } } catch (error) { console.error("获取好友详情失败:", error); setFriendDetailError("网络错误,请稍后重试"); } finally { setIsLoadingFriendDetail(false); } }; const getRestrictionLevelColor = (level: string) => { switch (level) { case "high": return "text-red-600"; case "medium": return "text-yellow-600"; default: return "text-gray-600"; } }; const formatDateTime = (dateString: string) => { const date = new Date(dateString); return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-'); }; const handleSearch = () => { // 搜索时重置空状态 setIsFriendsEmpty(false); setHasFriendLoadError(false); fetchFriends(1, true); }; const handleTabChange = (value: string) => { setActiveTab(value); }; if (!currentAccount) { return (
); } return ( } >
{/* 账号基本信息卡片 */}
{currentAccount.nickname}

{currentAccount.nickname}

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

微信号:{currentAccount.wechatAccount}

{/* 标签页 */}
{activeTab === "overview" ? (
{/* 账号基础信息 */}
账号年龄
{accountSummary && (
注册于 {new Date(accountSummary.accountAge).toLocaleDateString()}
)}
{accountSummary && (
{formatAccountAge(calculateAccountAge(accountSummary.accountAge))}
)}
活跃程度
{accountSummary && (
总聊天 {accountSummary.activityLevel.allTimes.toLocaleString()} 次
)}
{accountSummary && (
{accountSummary.activityLevel.dayTimes.toLocaleString()} 次/天
)}
{/* 账号权重评估 */} {accountSummary && (
账号权重评估
{accountSummary.accountWeight.scope}

{getWeightDescription(accountSummary.accountWeight.scope)}

账号年龄
{accountSummary.accountWeight.ageWeight}%
活跃度
{accountSummary.accountWeight.activityWeigth}%
限制影响
{accountSummary.accountWeight.restrictWeight}%
实名认证
{accountSummary.accountWeight.realNameWeight}%
)} {/* 添加好友统计 */} {accountSummary && (
添加好友统计
根据账号权重计算每日可添加好友数量
今日已添加 {accountSummary.statistics.todayAdded}
添加进度 {accountSummary.statistics.todayAdded}/{accountSummary.statistics.addLimit}
根据当前账号权重 ({accountSummary.accountWeight.scope}分),每日最多可添加{" "} {accountSummary.statistics.addLimit.toLocaleString()}{" "} 个好友
)} {/* 限制记录 */} {accountSummary && (
限制记录
{accountSummary.restrictions.length > 0 && ( )}
{accountSummary.restrictions.length > 0 ? (
{accountSummary.restrictions.slice(0, 2).map((record) => (
{record.reason} {formatDateTime(record.date)}
限制时间:{formatDateTime(record.date)}
))}
) : (
暂无风险记录
请继续保持良好的使用习惯
)}
)}
) : (
{/* 搜索栏 */}
setSearchQuery(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className="w-full pl-9 pr-3 py-2 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white" />
{/* 好友列表 */}
{isFetchingFriends && friends.length === 0 ? (
) : hasFriendLoadError ? (

加载失败,请稍后重试

) : isFriendsEmpty ? (

未找到匹配的好友

{searchQuery && ( )}
) : friends.length === 0 ? (
暂无好友数据
) : ( <> {friends.map((friend) => (
handleFriendClick(friend)} > {friend.nickname}
{friend.nickname} {friend.remark && ({friend.remark})}
{friend.wechatId}
{friend.tags?.map((tag, index) => ( {typeof tag === 'string' ? tag : tag.name} ))}
))} {hasMoreFriends && !isFriendsEmpty && (
)} )}
)}
{/* 这里补上,闭合415行的
*/} {/* 限制记录详情弹窗 */} {showRestrictions && (

限制记录详情

每次限制恢复时间为24小时

{(accountSummary?.restrictions && accountSummary.restrictions.length > 0) ? ( accountSummary.restrictions.map((record) => (
{record.reason}
{formatDateTime(record.date)}
恢复时间:{formatDateTime(record.date)}
)) ) : (
暂无风险记录,请继续保持
)}
)} {/* 好友转移确认对话框 */} {showTransferConfirm && (

好友转移确认

即将导出该微信号的好友列表,用于创建新的获客计划

{currentAccount.nickname}
{currentAccount.nickname}
{currentAccount.wechatId}

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

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

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

)} {/* 好友详情对话框 */} {showFriendDetail && (

好友详情

{isLoadingFriendDetail ? (
) : friendDetailError ? (

{friendDetailError}

) : friendDetail && selectedFriend ? (
{selectedFriend.nickname}

{selectedFriend.nickname}

微信号:{selectedFriend.wechatId}

地区 {friendDetail.region || "未知"}
添加时间 {friendDetail.addDate}
来源 {friendDetail.source || "未知"}
{friendDetail.memo && (
备注 {friendDetail.memo}
)} {friendDetail.tags && friendDetail.tags.length > 0 && (
标签
{friendDetail.tags.map((tag, index) => ( {tag} ))}
)}
) : null}
)} ); }