Reorganize navigation and module structure based on new requirements. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
122 lines
4.5 KiB
TypeScript
122 lines
4.5 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Badge } from "@/components/ui/badge"
|
|
import { ChevronLeft, ChevronRight } from "lucide-react"
|
|
|
|
interface ScheduleCalendarDialogProps {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
}
|
|
|
|
const MOCK_SCHEDULE = [
|
|
{
|
|
day: 12,
|
|
tasks: [
|
|
{ name: "数据同步", type: "sync" },
|
|
{ name: "CLV训练", type: "model" },
|
|
],
|
|
},
|
|
{ day: 13, tasks: [{ name: "标签计算", type: "tagging" }] },
|
|
{
|
|
day: 14,
|
|
tasks: [
|
|
{ name: "数据清洗", type: "cleaning" },
|
|
{ name: "RFM评估", type: "model" },
|
|
],
|
|
},
|
|
{ day: 15, tasks: [{ name: "流失预警", type: "model" }] },
|
|
{ day: 16, tasks: [{ name: "数据同步", type: "sync" }] },
|
|
{ day: 18, tasks: [{ name: "用户分群", type: "tagging" }] },
|
|
{ day: 20, tasks: [{ name: "数据清洗", type: "cleaning" }] },
|
|
]
|
|
|
|
const TYPE_COLORS: Record<string, string> = {
|
|
sync: "bg-blue-100 text-blue-700",
|
|
cleaning: "bg-green-100 text-green-700",
|
|
tagging: "bg-purple-100 text-purple-700",
|
|
model: "bg-orange-100 text-orange-700",
|
|
}
|
|
|
|
export function ScheduleCalendarDialog({ open, onOpenChange }: ScheduleCalendarDialogProps) {
|
|
const [currentMonth, setCurrentMonth] = useState(new Date(2025, 11))
|
|
|
|
const daysInMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 0).getDate()
|
|
const firstDayOfMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), 1).getDay()
|
|
|
|
const days = Array.from({ length: daysInMonth }, (_, i) => i + 1)
|
|
const emptyDays = Array.from({ length: firstDayOfMonth }, (_, i) => i)
|
|
|
|
const getTasksForDay = (day: number) => {
|
|
return MOCK_SCHEDULE.find((s) => s.day === day)?.tasks || []
|
|
}
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-[800px]">
|
|
<DialogHeader>
|
|
<DialogTitle>调度日历</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1))}
|
|
>
|
|
<ChevronLeft className="w-4 h-4" />
|
|
</Button>
|
|
<span className="font-semibold">
|
|
{currentMonth.getFullYear()}年{currentMonth.getMonth() + 1}月
|
|
</span>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1))}
|
|
>
|
|
<ChevronRight className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-7 gap-1">
|
|
{["日", "一", "二", "三", "四", "五", "六"].map((day) => (
|
|
<div key={day} className="text-center text-sm font-medium text-gray-500 py-2">
|
|
{day}
|
|
</div>
|
|
))}
|
|
{emptyDays.map((i) => (
|
|
<div key={`empty-${i}`} className="h-24" />
|
|
))}
|
|
{days.map((day) => {
|
|
const tasks = getTasksForDay(day)
|
|
return (
|
|
<div key={day} className="h-24 border border-gray-100 rounded-lg p-1 hover:bg-gray-50">
|
|
<div className="text-sm font-medium text-gray-700">{day}</div>
|
|
<div className="space-y-1 mt-1">
|
|
{tasks.slice(0, 2).map((task, i) => (
|
|
<Badge key={i} className={`text-xs px-1 py-0 ${TYPE_COLORS[task.type]}`}>
|
|
{task.name}
|
|
</Badge>
|
|
))}
|
|
{tasks.length > 2 && <span className="text-xs text-gray-400">+{tasks.length - 2}更多</span>}
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-4 pt-4 border-t">
|
|
<span className="text-sm text-gray-500">图例:</span>
|
|
<Badge className="bg-blue-100 text-blue-700">数据同步</Badge>
|
|
<Badge className="bg-green-100 text-green-700">数据清洗</Badge>
|
|
<Badge className="bg-purple-100 text-purple-700">标签计算</Badge>
|
|
<Badge className="bg-orange-100 text-orange-700">模型训练</Badge>
|
|
</div>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|