import { Button, Divider, Input, Select, Space, Switch, Typography } from '@arco-design/web-react' import { useEffect, useMemo, useState } from 'react' export interface CronInputProps { value?: string onChange?: (value: string) => void } const DEFAULT_CRON = '0 2 * * *' // 常用预设 const PRESETS = [ { label: '每天 02:00', value: '0 2 * * *' }, { label: '每天 00:00', value: '0 0 * * *' }, { label: '每 6 小时', value: '0 */6 * * *' }, { label: '每 12 小时', value: '0 */12 * * *' }, { label: '每周日 03:00', value: '0 3 * * 0' }, { label: '每月 1 日 02:00', value: '0 2 1 * *' }, { label: '每 30 分钟', value: '*/30 * * * *' }, { label: '每小时整点', value: '0 * * * *' }, ] const HOUR_OPTIONS = Array.from({ length: 24 }, (_, i) => ({ label: `${String(i).padStart(2, '0')} 时`, value: String(i), })) const MINUTE_OPTIONS = Array.from({ length: 12 }, (_, i) => ({ label: `${String(i * 5).padStart(2, '0')} 分`, value: String(i * 5), })) const WEEKDAY_OPTIONS = [ { label: '周一', value: '1' }, { label: '周二', value: '2' }, { label: '周三', value: '3' }, { label: '周四', value: '4' }, { label: '周五', value: '5' }, { label: '周六', value: '6' }, { label: '周日', value: '0' }, ] const DAY_OPTIONS = Array.from({ length: 31 }, (_, i) => ({ label: `${i + 1} 日`, value: String(i + 1), })) type ScheduleMode = 'daily' | 'weekly' | 'monthly' | 'interval' // 将 cron 表达式转为自然语言中文描述 function describeCron(expr: string): string { const parts = expr.trim().split(/\s+/) if (parts.length !== 5) return '' const [minute, hour, day, _month, week] = parts // 每 N 分钟 if (minute.includes('/') && hour === '*' && day === '*' && week === '*') { return `每 ${minute.split('/')[1]} 分钟执行一次` } // 每 N 小时 if (minute !== '*' && hour.includes('/') && day === '*' && week === '*') { return `每 ${hour.split('/')[1]} 小时执行一次(在第 ${minute} 分)` } // 每小时 if (minute !== '*' && hour === '*' && day === '*' && week === '*') { return `每小时的第 ${minute} 分执行` } const hh = hour.padStart(2, '0') const mm = minute.padStart(2, '0') const time = `${hh}:${mm}` // 每周某天 if (day === '*' && week !== '*') { const weekNames: Record = { '0': '日', '1': '一', '2': '二', '3': '三', '4': '四', '5': '五', '6': '六', '7': '日' } const days = week.split(',').map((w) => `周${weekNames[w] || w}`).join('、') return `每${days} ${time} 执行` } // 每月某日 if (day !== '*' && week === '*') { return `每月 ${day} 日 ${time} 执行` } // 每天 if (day === '*' && week === '*' && hour !== '*' && !hour.includes('/')) { return `每天 ${time} 执行` } return '' } export function CronInput({ value, onChange }: CronInputProps) { const [cronExpr, setCronExpr] = useState(value || DEFAULT_CRON) const [isAdvanced, setIsAdvanced] = useState(false) const [showCustom, setShowCustom] = useState(false) // 自定义模式的状态 const [mode, setMode] = useState('daily') const [customHour, setCustomHour] = useState('2') const [customMinute, setCustomMinute] = useState('0') const [customWeekdays, setCustomWeekdays] = useState(['0']) const [customDay, setCustomDay] = useState('1') const [customInterval, setCustomInterval] = useState('6') // 从 prop 同步 useEffect(() => { if (value !== undefined && value !== cronExpr) { setCronExpr(value || DEFAULT_CRON) } }, [value]) const description = useMemo(() => describeCron(cronExpr), [cronExpr]) const isPreset = PRESETS.some((p) => p.value === cronExpr) const emit = (expr: string) => { setCronExpr(expr) onChange?.(expr) } // 从自定义选择器构建 cron const buildCustomCron = ( m: ScheduleMode, h: string, min: string, weekdays: string[], day: string, interval: string, ) => { switch (m) { case 'daily': return `${min} ${h} * * *` case 'weekly': return `${min} ${h} * * ${weekdays.sort().join(',') || '0'}` case 'monthly': return `${min} ${h} ${day} * *` case 'interval': return `0 */${interval} * * *` default: return DEFAULT_CRON } } const handleCustomChange = (updates: { mode?: ScheduleMode hour?: string minute?: string weekdays?: string[] day?: string interval?: string }) => { const m = updates.mode ?? mode const h = updates.hour ?? customHour const min = updates.minute ?? customMinute const w = updates.weekdays ?? customWeekdays const d = updates.day ?? customDay const iv = updates.interval ?? customInterval if (updates.mode !== undefined) setMode(m) if (updates.hour !== undefined) setCustomHour(h) if (updates.minute !== undefined) setCustomMinute(min) if (updates.weekdays !== undefined) setCustomWeekdays(w) if (updates.day !== undefined) setCustomDay(d) if (updates.interval !== undefined) setCustomInterval(iv) emit(buildCustomCron(m, h, min, w, d, iv)) } return (
{/* 预设按钮 */} {PRESETS.map((preset) => ( ))} {/* 中文描述 + cron 表达式 */}
{ if (isAdvanced) emit(val) }} /> {description && ( {description} )}
手动输入 { setIsAdvanced(checked) setShowCustom(false) if (!checked) { setCronExpr(cronExpr) } }} />
{/* 自定义选择器 */} {showCustom && !isAdvanced && (
{mode === 'interval' ? ( handleCustomChange({ day: val })} />
)} 执行时间 handleCustomChange({ minute: val })} /> )}
)} ) }