Files
ckb-SuperAdmin/nkebao/src/pages/plans/PlanDetail.tsx
2025-07-05 21:40:14 +08:00

239 lines
8.7 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { ArrowLeft, Users, TrendingUp, Calendar, Settings, Play, Pause, Edit } from 'lucide-react';
interface PlanData {
id: string;
name: string;
status: 'active' | 'paused' | 'completed';
createdAt: string;
totalCustomers: number;
todayCustomers: number;
growth: string;
description?: string;
scenario: string;
}
export default function PlanDetail() {
const { planId } = useParams<{ planId: string }>();
const navigate = useNavigate();
const [plan, setPlan] = useState<PlanData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
useEffect(() => {
const fetchPlanData = async () => {
setLoading(true);
try {
// 模拟API调用
const mockPlan: PlanData = {
id: planId || '',
name: '春季营销计划',
status: 'active',
createdAt: '2024-03-15',
totalCustomers: 456,
todayCustomers: 23,
growth: '+8.2%',
description: '针对春季市场的营销推广计划,通过多种渠道获取潜在客户',
scenario: 'douyin',
};
setPlan(mockPlan);
} catch (error) {
setError('获取计划数据失败');
console.error('获取计划数据失败:', error);
} finally {
setLoading(false);
}
};
fetchPlanData();
}, [planId]);
const handleStatusChange = async (newStatus: 'active' | 'paused') => {
if (!plan) return;
try {
// 这里可以调用实际的API
// await fetch(`/api/plans/${plan.id}/status`, {
// method: 'PATCH',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ status: newStatus }),
// });
setPlan({ ...plan, status: newStatus });
} catch (error) {
console.error('更新计划状态失败:', error);
alert('更新失败,请重试');
}
};
if (loading) {
return (
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
<div className="flex justify-center items-center h-40">
<div className="text-gray-500">...</div>
</div>
</div>
);
}
if (error || !plan) {
return (
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
<div className="text-red-500 text-center py-8">{error || '计划不存在'}</div>
</div>
);
}
return (
<div className="flex-1 overflow-y-auto pb-20 bg-gray-50">
<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">
<button
onClick={() => navigate(-1)}
className="mr-3 p-1 hover:bg-gray-100 rounded"
>
<ArrowLeft className="h-5 w-5" />
</button>
<h1 className="text-xl font-semibold">{plan.name}</h1>
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => navigate(`/plans/${plan.id}/edit`)}
className="p-2 hover:bg-gray-100 rounded"
>
<Edit className="h-5 w-5" />
</button>
<button
onClick={() => navigate(`/plans/${plan.id}/settings`)}
className="p-2 hover:bg-gray-100 rounded"
>
<Settings className="h-5 w-5" />
</button>
</div>
</div>
</header>
<div className="p-4">
{/* 计划描述 */}
{plan.description && (
<div className="bg-white rounded-lg p-4 mb-6">
<p className="text-gray-600 text-sm">{plan.description}</p>
</div>
)}
{/* 数据统计 */}
<div className="grid grid-cols-2 gap-4 mb-6">
<div className="bg-white rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-500 text-sm"></p>
<p className="text-2xl font-bold text-gray-900">{plan.totalCustomers}</p>
</div>
<Users className="h-8 w-8 text-blue-500" />
</div>
<div className="flex items-center mt-2 text-green-500 text-sm">
<TrendingUp className="h-4 w-4 mr-1" />
<span>{plan.growth}</span>
</div>
</div>
<div className="bg-white rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-500 text-sm"></p>
<p className="text-2xl font-bold text-gray-900">{plan.todayCustomers}</p>
</div>
<Calendar className="h-8 w-8 text-green-500" />
</div>
<div className="flex items-center mt-2 text-gray-500 text-sm">
<span> {plan.createdAt}</span>
</div>
</div>
</div>
{/* 状态控制 */}
<div className="bg-white rounded-lg p-4 mb-6">
<h3 className="text-lg font-medium mb-4"></h3>
<div className="flex items-center justify-between">
<div className="flex items-center">
<span className={`px-3 py-1 rounded-full text-sm ${
plan.status === 'active'
? 'text-green-600 bg-green-50'
: plan.status === 'paused'
? 'text-yellow-600 bg-yellow-50'
: 'text-gray-600 bg-gray-50'
}`}>
{plan.status === 'active' ? '进行中' : plan.status === 'paused' ? '已暂停' : '已完成'}
</span>
</div>
<div className="flex space-x-2">
{plan.status === 'active' ? (
<button
onClick={() => handleStatusChange('paused')}
className="flex items-center px-3 py-2 bg-yellow-500 text-white rounded-md hover:bg-yellow-600 transition-colors text-sm"
>
<Pause className="h-4 w-4 mr-1" />
</button>
) : plan.status === 'paused' ? (
<button
onClick={() => handleStatusChange('active')}
className="flex items-center px-3 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors text-sm"
>
<Play className="h-4 w-4 mr-1" />
</button>
) : null}
</div>
</div>
</div>
{/* 功能区域 */}
<div className="grid grid-cols-2 gap-4">
<div className="bg-white rounded-lg p-4 cursor-pointer hover:shadow-md transition-shadow" onClick={() => navigate(`/plans/${plan.id}/customers`)}>
<div className="flex items-center">
<Users className="h-8 w-8 text-blue-500 mr-3" />
<div>
<h3 className="font-medium text-gray-900"></h3>
<p className="text-sm text-gray-500"></p>
</div>
</div>
</div>
<div className="bg-white rounded-lg p-4 cursor-pointer hover:shadow-md transition-shadow" onClick={() => navigate(`/plans/${plan.id}/analytics`)}>
<div className="flex items-center">
<TrendingUp className="h-8 w-8 text-green-500 mr-3" />
<div>
<h3 className="font-medium text-gray-900"></h3>
<p className="text-sm text-gray-500"></p>
</div>
</div>
</div>
<div className="bg-white rounded-lg p-4 cursor-pointer hover:shadow-md transition-shadow" onClick={() => navigate(`/plans/${plan.id}/content`)}>
<div className="flex items-center">
<Calendar className="h-8 w-8 text-purple-500 mr-3" />
<div>
<h3 className="font-medium text-gray-900"></h3>
<p className="text-sm text-gray-500"></p>
</div>
</div>
</div>
<div className="bg-white rounded-lg p-4 cursor-pointer hover:shadow-md transition-shadow" onClick={() => navigate(`/plans/${plan.id}/settings`)}>
<div className="flex items-center">
<Settings className="h-8 w-8 text-gray-500 mr-3" />
<div>
<h3 className="font-medium text-gray-900"></h3>
<p className="text-sm text-gray-500"></p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}