"use client" import { useState, useCallback, useRef, useEffect } from "react" import { useRouter, useSearchParams } from "next/navigation" import { Card } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { ChevronLeft, Filter, Search, RefreshCw, Tag } from "lucide-react" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination" import { useToast } from "@/components/ui/use-toast" import { useDebounce } from "@/hooks/use-debounce" import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Badge } from "@/components/ui/badge" interface UserTag { id: string name: string color: string } interface TrafficUser { id: string avatar: string nickname: string wechatId: string phone: string region: string note: string status: "pending" | "added" | "failed" addTime: string source: string assignedTo: string category: "potential" | "customer" | "lost" tags: UserTag[] } export default function TrafficPoolPage() { const router = useRouter() const searchParams = useSearchParams() const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) // Start with loading state const [activeCategory, setActiveCategory] = useState("potential") // Changed default from "all" to "potential" const [sourceFilter, setSourceFilter] = useState("all") const [statusFilter, setStatusFilter] = useState("all") const [searchQuery, setSearchQuery] = useState("") const [currentPage, setCurrentPage] = useState(1) const [totalPages, setTotalPages] = useState(1) const [stats, setStats] = useState({ total: 0, todayNew: 0, }) const [selectedUser, setSelectedUser] = useState(null) const [showUserDetail, setShowUserDetail] = useState(false) const { toast } = useToast() const abortControllerRef = useRef(null) const debouncedSearchQuery = useDebounce(searchQuery, 300) const fetchUsers = useCallback(async () => { try { if (abortControllerRef.current) { abortControllerRef.current.abort() } abortControllerRef.current = new AbortController() setLoading(true) const params = new URLSearchParams({ page: currentPage.toString(), pageSize: "10", search: debouncedSearchQuery, category: activeCategory, source: sourceFilter, status: statusFilter, }) // 检查是否有来源参数 const sourceParam = searchParams.get("source") if (sourceParam) { params.append("wechatSource", sourceParam) } const response = await fetch(`/api/users?${params}`, { signal: abortControllerRef.current.signal, }) if (!response.ok) throw new Error("请求失败") const data = await response.json() // 为每个用户添加标签 const usersWithTags = data.users.map((user: TrafficUser) => { // 生成随机标签 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" }, ] const tags = Array.from({ length: Math.floor(Math.random() * 4) + 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, } }) return { ...user, tags, } }) setUsers(usersWithTags) setTotalPages(data.pagination.totalPages) setStats(data.stats) } catch (error) { if (error instanceof Error && error.name === "AbortError") { return } toast({ title: "错误", description: "获取数据失败,请稍后重试", variant: "destructive", }) } finally { setLoading(false) } }, [currentPage, debouncedSearchQuery, activeCategory, sourceFilter, statusFilter, toast, searchParams]) useEffect(() => { fetchUsers() return () => { if (abortControllerRef.current) { abortControllerRef.current.abort() } } }, [fetchUsers]) const handleUserClick = (user: TrafficUser) => { setSelectedUser(user) setShowUserDetail(true) } return (

流量池

{/* 搜索和筛选区域 */}
{ setSearchQuery(e.target.value) setCurrentPage(1) }} className="pl-9" />
{/* 统计卡片 */}
流量池总数
{stats.total}
今日新增
{stats.todayNew}
{/* 分类标签页 - 移除了"全部"选项 */} { setActiveCategory(value) setCurrentPage(1) }} > 潜在客户 已转化 {/* 筛选器 */}
{/* 用户列表 - 改进加载状态显示 */}
{loading ? (
加载中...
) : users.length === 0 ? (
暂无数据
) : ( users.map((user) => ( handleUserClick(user)} >
{user.nickname}
{user.status === "added" ? "已添加" : user.status === "pending" ? "待处理" : "已失败"}
微信号: {user.wechatId}
来源: {user.source}
添加时间: {new Date(user.addTime).toLocaleString()}
{/* 标签展示 */}
{user.tags.slice(0, 2).map((tag) => ( {tag.name} ))} {user.tags.length > 2 && ( +{user.tags.length - 2} )}
)) )}
{/* 分页 */} {!loading && users.length > 0 && ( { e.preventDefault() setCurrentPage((prev) => Math.max(1, prev - 1)) }} /> {Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => ( { e.preventDefault() setCurrentPage(page) }} > {page} ))} { e.preventDefault() setCurrentPage((prev) => Math.min(totalPages, prev + 1)) }} /> )}
{/* 用户详情弹窗 */} 用户详情 {selectedUser && (
{selectedUser.nickname[0]}
{selectedUser.nickname}
{selectedUser.wechatId}
{selectedUser.status === "added" ? "已添加" : selectedUser.status === "pending" ? "待处理" : "已失败"}
手机号码
{selectedUser.phone}
地区
{selectedUser.region}
来源
{selectedUser.source}
添加时间
{new Date(selectedUser.addTime).toLocaleString()}
标签
{selectedUser.tags.map((tag) => ( {tag.name} ))} {selectedUser.tags.length === 0 && 暂无标签}
{selectedUser.note && (
备注信息
{selectedUser.note}
)}
)}
) }