| 1 | import { useState, useEffect } from 'react'; |
| 2 | import { Select, Input, Button, message, Form } from 'antd'; |
| 3 | |
| 4 | interface CronScheduleProps { |
| 5 | onSubmit: (cronExpression: string) => void; |
| 6 | } |
| 7 | |
| 8 | const CronSchedule: React.FC<CronScheduleProps> = ({ onSubmit }) => { |
| 9 | const [selectedType, setSelectedType] = useState('day'); |
| 10 | const [value, setValue] = useState(''); |
| 11 | const [error, setError] = useState(''); |
| 12 | |
| 13 | const handleTypeChange = (value: string) => { |
| 14 | setSelectedType(value); |
| 15 | setValue(''); // 切换类型时重置输入值 |
| 16 | }; |
| 17 | |
| 18 | const handleValueChange = (e: React.ChangeEvent<HTMLInputElement>) => { |
| 19 | setValue(e.target.value); |
| 20 | }; |
| 21 | |
| 22 | const handleSubmit = () => { |
| 23 | if (validate()) { |
| 24 | const cronExpression = `${selectedType}-${value}`; |
| 25 | onSubmit(cronExpression); |
| 26 | message.success('定时表达式生成成功'); |
| 27 | } |
| 28 | }; |
| 29 | |
| 30 | const validate = (): boolean => { |
| 31 | let isValid = true; |
| 32 | let errorMessage = ''; |
| 33 | const valueInt = parseInt(value, 10); |
| 34 | |
| 35 | switch (selectedType) { |
| 36 | case 'day': |
| 37 | if (isNaN(valueInt) || valueInt < 0 || valueInt > 23) { |
| 38 | errorMessage = '小时必须是0-23的整数'; |
| 39 | isValid = false; |
| 40 | } |
| 41 | break; |
| 42 | case 'week': |
| 43 | if (isNaN(valueInt) || valueInt < 0 || valueInt > 6) { |
| 44 | errorMessage = '周必须是0(周日)到6(周六)的整数'; |
| 45 | isValid = false; |
| 46 | } |
| 47 | break; |
| 48 | case 'month': |
| 49 | if (isNaN(valueInt) || valueInt < 1 || valueInt > 31) { |
| 50 | errorMessage = '日期必须是1-31的整数'; |
| 51 | isValid = false; |
| 52 | } |
| 53 | break; |
| 54 | default: |
| 55 | isValid = false; |
| 56 | } |
| 57 | |
| 58 | setError(errorMessage); |
| 59 | return isValid; |
| 60 | }; |
| 61 | |
| 62 | return ( |
| 63 | <Form layout="vertical" style={{ width: 300 }}> |
| 64 | <Form.Item label="周期类型"> |
| 65 | <Select |
| 66 | value={selectedType} |
| 67 | onChange={handleTypeChange} |
| 68 | style={{ width: '100%' }} |
| 69 | > |
| 70 | <Select.Option value="day">每天</Select.Option> |
| 71 | <Select.Option value="week">每周</Select.Option> |
| 72 | <Select.Option value="month">每月</Select.Option> |
| 73 | </Select> |
| 74 | </Form.Item> |
| 75 | |
| 76 | <Form.Item label="参数设置"> |
| 77 | <Input |
| 78 | type="number" |
| 79 | min={selectedType === 'month' ? 1 : 0} |
| 80 | max={selectedType === 'day' ? 23 : selectedType === 'week' ? 6 : 31} |
| 81 | value={value} |
| 82 | onChange={handleValueChange} |
| 83 | placeholder={ |
| 84 | selectedType === 'day' |
| 85 | ? '小时(0-23)' |
| 86 | : selectedType === 'week' |
| 87 | ? '周几(0=周日)' |
| 88 | : '日期(1-31)' |
| 89 | } |
| 90 | required |
| 91 | style={{ width: '100%' }} |
| 92 | /> |
| 93 | {error && <div style={{ color: '#f5222d', fontSize: 12 }}>{error}</div>} |
| 94 | </Form.Item> |
| 95 | |
| 96 | <Form.Item> |
| 97 | <Button |
| 98 | type="primary" |
| 99 | onClick={handleSubmit} |
| 100 | disabled={!value || !!error} |
| 101 | style={{ width: '100%' }} |
| 102 | > |
| 103 | 生成定时表达式 |
| 104 | </Button> |
| 105 | </Form.Item> |
| 106 | </Form> |
| 107 | ); |
| 108 | }; |
| 109 | |
| 110 | // 解析组件 |
| 111 | const ParseCronSchedule: React.FC<{ cronExpression: string }> = ({ |
| 112 | cronExpression, |
| 113 | }) => { |
| 114 | const [parsedText, setParsedText] = useState(''); |
| 115 | |
| 116 | useEffect(() => { |
| 117 | const [type, value] = cronExpression.split('-'); |
| 118 | let parsed = ''; |
| 119 | switch (type) { |
| 120 | case 'day': |
| 121 | parsed = `每天${value}时`; |
| 122 | break; |
| 123 | case 'week': |
| 124 | parsed = `每周周${value}`; |
| 125 | break; |
| 126 | case 'month': |
| 127 | parsed = `每月${value}号`; |
| 128 | break; |
| 129 | default: |
| 130 | parsed = '未知类型'; |
| 131 | } |
| 132 | setParsedText(parsed); |
| 133 | }, [cronExpression]); |
| 134 | |
| 135 | return <p>{parsedText}</p>; |
| 136 | }; |
| 137 | |
| 138 | export { CronSchedule, ParseCronSchedule }; |
| 139 |