"use client" import { useState, useEffect } from "react" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Input } from "@/components/ui/input" import { Switch } from "@/components/ui/switch" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Label } from "@/components/ui/label" import { Calendar, Plus, Play, Pause, RefreshCw, Clock, CheckCircle2, XCircle, Loader2, Settings, Database, Zap, Target, } from "lucide-react" // 任务接口 interface Task { id: string name: string description: string type: 'sync' | 'clean' | 'tag' | 'export' source: string target: string schedule: string enabled: boolean lastRun?: string lastStatus?: 'success' | 'failed' | 'running' nextRun?: string processedCount?: number } // 预定义任务 const DEFAULT_TASKS: Task[] = [ { id: 'task_1', name: '腾讯QQ数据同步', description: '从KR_腾讯同步QQ手机关联数据到用户估值表', type: 'sync', source: 'KR_腾讯', target: 'KR.用户估值', schedule: '每小时', enabled: true, lastRun: '10分钟前', lastStatus: 'success', nextRun: '50分钟后', processedCount: 1250000 }, { id: 'task_2', name: '微博UID关联', description: '从KR_微博同步UID与手机号关联', type: 'sync', source: 'KR_微博', target: 'KR.用户估值', schedule: '每天凌晨', enabled: true, lastRun: '昨天 02:00', lastStatus: 'success', nextRun: '明天 02:00', processedCount: 5800000 }, { id: 'task_3', name: '存客宝CRM同步', description: '从MySQL同步存客宝用户数据', type: 'sync', source: 'cunkebao_v3', target: 'KR_存客宝.用户资产统一视图', schedule: '每5分钟', enabled: true, lastRun: '2分钟前', lastStatus: 'success', nextRun: '3分钟后', processedCount: 350 }, { id: 'task_4', name: '手机号格式化清洗', description: '清洗手机号格式,补充归属地信息', type: 'clean', source: 'KR.用户估值', target: 'KR.用户估值', schedule: '每小时', enabled: true, lastRun: '30分钟前', lastStatus: 'success', processedCount: 95000 }, { id: 'task_5', name: 'RFM评分计算', description: '计算用户RFM评分并更新用户等级', type: 'tag', source: 'KR.用户估值', target: 'KR.用户估值', schedule: '每天凌晨', enabled: true, lastRun: '昨天 03:00', lastStatus: 'success', processedCount: 20000000 }, { id: 'task_6', name: '流量包导出', description: '导出高价值用户流量包', type: 'export', source: 'KR.用户估值', target: '文件系统', schedule: '按需', enabled: false, lastRun: '3天前', lastStatus: 'success', processedCount: 50000 }, ] export default function TaskSchedulePage() { const [tasks, setTasks] = useState(DEFAULT_TASKS) const [loading, setLoading] = useState(false) const [showAddDialog, setShowAddDialog] = useState(false) const [runningTask, setRunningTask] = useState(null) // 任务类型配置 const TASK_TYPES = { sync: { label: '数据同步', color: 'bg-blue-100 text-blue-700', icon: RefreshCw }, clean: { label: '数据清洗', color: 'bg-green-100 text-green-700', icon: Zap }, tag: { label: '标签计算', color: 'bg-purple-100 text-purple-700', icon: Target }, export: { label: '数据导出', color: 'bg-orange-100 text-orange-700', icon: Database }, } // 执行任务 const runTask = async (taskId: string) => { setRunningTask(taskId) // 模拟执行 await new Promise(r => setTimeout(r, 2000)) setTasks(tasks.map(t => t.id === taskId ? { ...t, lastRun: '刚刚', lastStatus: 'success' as const } : t)) setRunningTask(null) } // 切换任务状态 const toggleTask = (taskId: string) => { setTasks(tasks.map(t => t.id === taskId ? { ...t, enabled: !t.enabled } : t)) } const formatNumber = (num: number): string => { if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M` if (num >= 1000) return `${(num / 1000).toFixed(0)}K` return num.toLocaleString() } const getStatusIcon = (status?: string) => { switch (status) { case 'success': return case 'failed': return case 'running': return default: return } } return (
{/* 顶部标题 */}

任务调度

管理数据同步、清洗、计算等定时任务

{/* 统计卡片 */}

任务总数

{tasks.length}

运行中

{tasks.filter(t => t.enabled).length}

今日执行

128

处理数据

{formatNumber(tasks.reduce((sum, t) => sum + (t.processedCount || 0), 0))}

{/* 任务列表 */}
{tasks.map((task) => { const typeConfig = TASK_TYPES[task.type] const TypeIcon = typeConfig.icon const isRunning = runningTask === task.id return (

{task.name}

{typeConfig.label} {!task.enabled && 已暂停}

{task.description}

{task.source} → {task.target} {task.schedule} {task.lastRun && ( {getStatusIcon(task.lastStatus)} 上次: {task.lastRun} )} {task.processedCount && ( 处理: {formatNumber(task.processedCount)} 条 )}
toggleTask(task.id)} />
) })}
{/* 新建任务弹窗 */} 新建任务 创建新的数据处理任务
) }