超管后台 - 简化项目代码,移除掉接口返回错误时使用的虚假模拟数据

This commit is contained in:
柳清爽
2025-04-24 14:20:02 +08:00
parent 4a5b2eaa1e
commit 42d9cb6be5
3 changed files with 67 additions and 233 deletions

View File

@@ -21,46 +21,6 @@ import {
AlertDialogTitle,
} from "@/components/ui/alert-dialog"
// 保留原始示例数据,作为加载失败时的备用数据
const adminsData = [
{
id: "1",
account: "admin_zhang",
username: "张管理",
role: "超级管理员",
permissions: ["项目管理", "客户池", "管理员权限"],
createdAt: "2023-05-01",
lastLogin: "2023-06-28 09:15",
},
{
id: "2",
account: "admin_li",
username: "李管理",
role: "项目管理员",
permissions: ["项目管理", "客户池"],
createdAt: "2023-05-10",
lastLogin: "2023-06-27 14:30",
},
{
id: "3",
account: "admin_wang",
username: "王管理",
role: "客户管理员",
permissions: ["客户池"],
createdAt: "2023-05-15",
lastLogin: "2023-06-28 11:45",
},
{
id: "4",
account: "admin_zhao",
username: "赵管理",
role: "项目管理员",
permissions: ["项目管理"],
createdAt: "2023-05-20",
lastLogin: "2023-06-26 16:20",
},
]
export default function AdminsPage() {
const [searchTerm, setSearchTerm] = useState("")
const [isLoading, setIsLoading] = useState(true)
@@ -95,14 +55,8 @@ export default function AdminsPage() {
description: response.msg || "请稍后重试",
variant: "destructive",
})
// 加载失败时显示示例数据
setAdministrators(adminsData.map(admin => ({
...admin,
id: Number(admin.id),
name: admin.username,
status: 1
})))
setTotalCount(adminsData.length)
setAdministrators([])
setTotalCount(0)
}
} catch (error) {
console.error("获取管理员列表出错:", error)
@@ -111,14 +65,8 @@ export default function AdminsPage() {
description: "请检查网络连接后重试",
variant: "destructive",
})
// 加载失败时显示示例数据
setAdministrators(adminsData.map(admin => ({
...admin,
id: Number(admin.id),
name: admin.username,
status: 1
})))
setTotalCount(adminsData.length)
setAdministrators([])
setTotalCount(0)
} finally {
setIsLoading(false)
}

View File

@@ -20,94 +20,6 @@ import { getTrafficPoolList } from "@/lib/traffic-pool-api"
import { Customer } from "@/lib/traffic-pool-api"
import { PaginationControls } from "@/components/ui/pagination-controls"
// Sample customer data
const customersData = [
{
id: "1",
name: "张三",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "zhangsan123",
gender: "男",
region: "北京",
source: "微信搜索",
tags: ["潜在客户", "高消费"],
projectName: "电商平台项目",
addedDate: "2023-06-10",
},
{
id: "2",
name: "李四",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "lisi456",
gender: "男",
region: "上海",
source: "朋友推荐",
tags: ["活跃用户"],
projectName: "社交媒体营销",
addedDate: "2023-06-12",
},
{
id: "3",
name: "王五",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "wangwu789",
gender: "男",
region: "广州",
source: "广告点击",
tags: ["新用户"],
projectName: "企业官网推广",
addedDate: "2023-06-15",
},
{
id: "4",
name: "赵六",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "zhaoliu321",
gender: "男",
region: "深圳",
source: "线下活动",
tags: ["高消费", "忠诚客户"],
projectName: "教育平台项目",
addedDate: "2023-06-18",
},
{
id: "5",
name: "钱七",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "qianqi654",
gender: "女",
region: "成都",
source: "微信群",
tags: ["潜在客户"],
projectName: "金融服务推广",
addedDate: "2023-06-20",
},
{
id: "6",
name: "孙八",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "sunba987",
gender: "女",
region: "武汉",
source: "微信搜索",
tags: ["活跃用户", "高消费"],
projectName: "电商平台项目",
addedDate: "2023-06-22",
},
{
id: "7",
name: "周九",
avatar: "/placeholder.svg?height=40&width=40",
wechatId: "zhoujiu135",
gender: "女",
region: "杭州",
source: "朋友推荐",
tags: ["新用户"],
projectName: "社交媒体营销",
addedDate: "2023-06-25",
},
]
export default function CustomersPage() {
const [searchTerm, setSearchTerm] = useState("")
const [selectedRegion, setSelectedRegion] = useState("")
@@ -162,25 +74,6 @@ export default function CustomersPage() {
setCurrentPage(1); // Reset to first page when page size changes
};
// Filter customers based on search and filters (兼容示例数据)
const filteredCustomers = customersData.filter((customer) => {
const matchesSearch =
customer.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
customer.wechatId.toLowerCase().includes(searchTerm.toLowerCase())
const matchesRegion = selectedRegion ? customer.region === selectedRegion : true
const matchesGender = selectedGender ? customer.gender === selectedGender : true
const matchesSource = selectedSource ? customer.source === selectedSource : true
const matchesProject = selectedProject ? customer.projectName === selectedProject : true
return matchesSearch && matchesRegion && matchesGender && matchesSource && matchesProject
})
// Get unique values for filters
const regions = [...new Set(customersData.map((c) => c.region))]
const sources = [...new Set(customersData.map((c) => c.source))]
const projects = [...new Set(customersData.map((c) => c.projectName))]
return (
<div className="space-y-6">
<div className="flex justify-between">
@@ -217,11 +110,7 @@ export default function CustomersPage() {
</SelectTrigger>
<SelectContent>
<SelectItem value="all"></SelectItem>
{regions.map((region) => (
<SelectItem key={region} value={region}>
{region}
</SelectItem>
))}
{/* 从API获取到的regions数据应在此处映射 */}
</SelectContent>
</Select>
</div>
@@ -248,28 +137,20 @@ export default function CustomersPage() {
</SelectTrigger>
<SelectContent>
<SelectItem value="all"></SelectItem>
{sources.map((source) => (
<SelectItem key={source} value={source}>
{source}
</SelectItem>
))}
{/* 从API获取到的sources数据应在此处映射 */}
</SelectContent>
</Select>
</div>
<DropdownMenuSeparator />
<div className="p-2">
<p className="mb-2 text-sm font-medium"></p>
<p className="mb-2 text-sm font-medium"></p>
<Select value={selectedProject} onValueChange={setSelectedProject}>
<SelectTrigger>
<SelectValue placeholder="所有项目" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all"></SelectItem>
{projects.map((project) => (
<SelectItem key={project} value={project}>
{project}
</SelectItem>
))}
{/* 从API获取到的projects数据应在此处映射 */}
</SelectContent>
</Select>
</div>
@@ -277,16 +158,16 @@ export default function CustomersPage() {
</DropdownMenu>
</div>
<div className="rounded-md border">
<div className="border rounded-md">
<Table>
<TableHeader>
<TableRow>
<TableHead></TableHead>
<TableHead>ID</TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead className="text-right"></TableHead>
</TableRow>
@@ -294,45 +175,45 @@ export default function CustomersPage() {
<TableBody>
{isLoading ? (
<TableRow>
<TableCell colSpan={8} className="h-24 text-center">
...
</TableCell>
<TableCell colSpan={8} className="text-center py-4">...</TableCell>
</TableRow>
) : error ? (
<TableRow>
<TableCell colSpan={8} className="h-24 text-center text-red-600">
{error}
</TableCell>
<TableCell colSpan={8} className="text-center py-4 text-red-500">{error}</TableCell>
</TableRow>
) : customers.length > 0 ? (
) : customers.length === 0 ? (
<TableRow>
<TableCell colSpan={8} className="text-center py-4"></TableCell>
</TableRow>
) : (
customers.map((customer) => (
<TableRow key={customer.id}>
<TableCell>
<div className="flex items-center gap-3">
<Avatar>
<AvatarImage
src={customer.avatar || "/placeholder.svg?height=40&width=40"}
alt={customer.nickname || "未知"}
onError={(e) => {
// 图片加载失败时使用默认图片
const target = e.target as HTMLImageElement;
target.src = "/placeholder.svg?height=40&width=40";
}}
/>
<AvatarFallback>{(customer.nickname || "未知").slice(0, 2)}</AvatarFallback>
<div className="flex items-center gap-2">
<Avatar className="h-8 w-8">
<AvatarImage src={customer.avatar || "/placeholder.svg?height=40&width=40"} alt={customer.nickname} />
<AvatarFallback>{customer.nickname ? customer.nickname.substring(0, 1) : "?"}</AvatarFallback>
</Avatar>
<div>
<div className="font-medium">{customer.nickname || "未知"}</div>
<div className="text-xs text-muted-foreground">{customer.gender}</div>
<div className="font-medium">{customer.nickname}</div>
<div className="text-sm text-muted-foreground">{customer.wechatId}</div>
</div>
</div>
</TableCell>
<TableCell>{customer.wechatId}</TableCell>
<TableCell>{customer.gender}</TableCell>
<TableCell>{customer.region}</TableCell>
<TableCell>{customer.source}</TableCell>
<TableCell>{customer.projectName}</TableCell>
<TableCell>{customer.addTime}</TableCell>
<TableCell>
<div className="flex flex-wrap gap-1">
{customer.tags && customer.tags.map((tag) => (
<Badge key={tag} variant="secondary">
{tag}
</Badge>
))}
</div>
</TableCell>
<TableCell>{customer.companyName}</TableCell>
<TableCell>{customer.createTime}</TableCell>
<TableCell className="text-right">
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -342,39 +223,41 @@ export default function CustomersPage() {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem asChild>
<Link href={`/dashboard/customers/${customer.id}`}>
<Eye className="mr-2 h-4 w-4" />
<DropdownMenuItem>
<Link href={`/dashboard/customers/${customer.id}`} className="flex items-center w-full">
<Eye className="mr-2 h-4 w-4" />
</Link>
</DropdownMenuItem>
<DropdownMenuItem>
<UserPlus className="mr-2 h-4 w-4" />
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem></DropdownMenuItem>
<DropdownMenuItem></DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={8} className="h-24 text-center">
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
{/* 使用新的分页组件 */}
<PaginationControls
currentPage={currentPage}
totalPages={totalPages}
pageSize={pageSize}
totalItems={totalItems}
onPageChange={setCurrentPage} // 直接传递setCurrentPage
onPageSizeChange={handlePageSizeChange}
/>
{/* 分页控制 */}
<div className="flex items-center justify-between">
<div className="text-sm text-muted-foreground">
{totalItems} {currentPage} {totalPages}
</div>
<div className="flex items-center space-x-2">
<PaginationControls
currentPage={currentPage}
totalPages={totalPages}
onPageChange={setCurrentPage}
onPageSizeChange={handlePageSizeChange}
pageSize={pageSize}
totalItems={totalItems}
/>
</div>
</div>
</div>
</div>
)

View File

@@ -28,6 +28,9 @@ interface Project {
deviceCount: number
friendCount: number
userCount: number
username: string
status: number
devices?: Device[]
}
export default function EditProjectPage({ params }: { params: { id: string } }) {
@@ -37,7 +40,7 @@ export default function EditProjectPage({ params }: { params: { id: string } })
const [project, setProject] = useState<Project | null>(null)
const [password, setPassword] = useState("")
const [confirmPassword, setConfirmPassword] = useState("")
const { id } = use(params)
const id = params.id
useEffect(() => {
const fetchProject = async () => {
@@ -82,8 +85,8 @@ export default function EditProjectPage({ params }: { params: { id: string } })
account: project?.account,
memo: project?.memo,
phone: project?.phone,
username: nickname,
status: parseInt(status),
username: project?.username,
status: project?.status,
...(password && { password })
}),
})
@@ -215,7 +218,7 @@ export default function EditProjectPage({ params }: { params: { id: string } })
<div className="space-y-2">
<Label></Label>
<div className="space-y-3">
{project?.devices.length > 0 && project.devices.map((device) => (
{project && project.devices && project.devices.length > 0 && project.devices.map((device) => (
<div key={device.id} className="flex items-center gap-2">
<Input
value={device.memo}