react 实现CRON表达式生成器功能
可以使用react-cron-builder,不过样式不美观,操作方式不习惯,部分表达式也无法生成;
参考地址:https://www.npmjs.com/package/react-cron-builder;
目前配合使用antd的UI简单的实现了基本功能,部分联动性操作及校验后续逐步完善;布局和操作方式主要参考:http://www.bejson.com/othertools/cron/
以下是部分截图:
以下是代码部分:
import React,{Component} from 'react'; import {Input, Button, InputNumber, Tabs, Switch, Select, Radio,Checkbox, Row, Col} from 'antd'; import './css/cronGenerator.css'; import {element} from "prop-types"; const { Option } = Select;
/**
*CRON表达式生成器
*@author Shellcoochi
*/ class CronGenerator extends Component{ constructor(props) { super(props); } state={ cronText:'* * * * * *', cronType:['second','minute','hour','day','month','week'], radioValue:{ second: 1, minute: 1, hour: 1, day: 1, month: 1, week: 1, }, periodValue: { second: {max:1,min:1}, minute: {max:1,min:1}, hour: {max:1,min:1}, day: {max:1,min:1}, month: {max:1,min:1}, week: {max:1,min:1}, }, loopValue: { second: {start:1,end:1}, minute: {start:1,end:1}, hour: {start:1,end:1}, day: {start:1,end:1}, month: {start:1,end:1}, week: {start:1,end:1}, }, cron: { second: '*', minute: '*', hour: '*', day: '*', month: '*', week: '*', }, cronParams: { second: '*', minute: '*', hour: '*', day: '*', month: '*', week: '*', } }; //生成cron createCron = async () => { let {cronType} = this.state; for(let type of cronType){ await this.cronGenerator(type); } let {second,minute,hour,day,month,week} = this.state.cron; let cronText = second+ ' '+minute+' '+hour+' '+day+' '+month+' '+week; this.setState({ cronText:cronText }) }; /** * cron生成器 * @param type */ cronGenerator = (type)=> { let srv = this.state.radioValue[type]; let period = this.state.periodValue[type]; let loop = this.state.loopValue[type]; let param = this.state.cronParams[type]; let data = ''; switch (srv) { case 1: data = '*';break; case 2: data = '?';break; case 'point': for (let v of param){ data = data+v+','; } data = data.substring(0, data.length - 1);break; case 'period': data = period.min+'-'+period.max; break; case 'loop': data = loop.start+'/'+loop.end; break; default: data = '*'; } this.setState({ cron:Object.assign({}, this.state.cron, this.cronItemGenerator(type,data)) }) }; /** * 对象生成器 * @param type * @param data * @returns {{second: *}|{minute: *}} */ cronItemGenerator = (type,data)=> { switch (type) { case 'second': return {second: data}; case 'minute': return {minute: data}; case 'hour': return {hour: data}; case 'day': return {day: data}; case 'month': return {month: data}; case 'week': return {week: data}; } }; /** * 生成多选框 * @param col 每行个数 * @param minNum 最小值 * @param maxNum 最大值 * @param key */ createCheckbox = (key,col,minNum,maxNum) => { let colArray = []; let rowArray = []; let count = col; let keyNum = minNum; for(minNum;minNum <= maxNum;minNum++){ let checkbox = <Checkbox key = {key+keyNum} value={minNum}>{this.formatNum(minNum)}</Checkbox>; if(count > 0){ colArray.push(checkbox); count--; if(minNum === maxNum)rowArray.push(<Col key={key+keyNum} span={24}>{colArray}</Col>) }else{ rowArray.push(<Col key = {key+keyNum} span={24}>{colArray}</Col>) colArray = []; minNum--; count = col; } keyNum++; } return <Row>{rowArray}</Row> }; /** * 格式化0~9的数字 * @param num */ formatNum = (num)=> { if(num < 10 && num > -1){ return '0'+num; } return num; }; handleRadioChange = (e,type)=> { this.setState({ radioValue: Object.assign({}, this.state.radioValue, this.cronItemGenerator(type,e.target.value)) }) }; handleCheckboxChange = (checkedValues,type) => { this.setState({ cronParams:Object.assign({}, this.state.cronParams, this.cronItemGenerator(type,checkedValues)) }); }; handlePeriodChange = (e,type,tar) => { let data = this.state.periodValue; data[type] = tar=='max'?{max: e,min:data[type].min}:{max: data[type].max,min:e}; this.setState({ periodValue: Object.assign({}, this.state.periodValue, this.cronItemGenerator(type,data[type])) }) }; handleLoopChange = (e,type,tar) => { let data = this.state.loopValue; data[type] = tar=='start'?{start: e,end:data[type].end}:{start: data[type].start,end:e}; this.setState({ loopValue: Object.assign({}, this.state.loopValue, this.cronItemGenerator(type,data[type])) }) }; render() { const { TabPane } = Tabs; const daysChildren = []; const {cronText,radioValue} = this.state; const { Search } = Input; const radioStyle = { display: 'block', height: '30px', lineHeight: '30px', }; const secondCheckbox = this.createCheckbox('second',10,0,59); const minuteCheckbox = this.createCheckbox('minute',10,0,59); const hourCheckbox = this.createCheckbox('hour',12,0,23); const dayCheckbox = this.createCheckbox('day',10,1,31); const monthCheckbox = this.createCheckbox('month',12,1,12); const weekCheckbox = this.createCheckbox('week',7,1,7); return( <> <Tabs type="card"> <TabPane tab="秒" key="1"> <Radio.Group onChange={e => this.handleRadioChange(e,'second')} value={radioValue['second']}> <Radio style={radioStyle} value={1}> 每秒执行 </Radio> <Radio style={radioStyle} value= 'period'> 周期从 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handlePeriodChange(e,'second','min')} /> - <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handlePeriodChange(e,'second','max')}/> 秒 </Radio> <Radio style={radioStyle} value='loop'> 从 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handleLoopChange(e,'second','start')}/> 秒开始,每 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handleLoopChange(e,'second','end')}/> 秒执行一次 </Radio> <Radio style={radioStyle} value='point'> <Checkbox.Group style={{ width: '100%' }} onChange={e => this.handleCheckboxChange(e,'second')} > 指定 {secondCheckbox} </Checkbox.Group> </Radio> </Radio.Group> </TabPane> <TabPane tab="分" key="2"> <Radio.Group value={radioValue['minute']} onChange={e => this.handleRadioChange(e,'minute')}> <Radio style={radioStyle} value={1}> 每分执行 </Radio> <Radio style={radioStyle} value='period'> 周期从 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handlePeriodChange(e,'minute','min')}/> - <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handlePeriodChange(e,'minute','max')}/> 分 </Radio> <Radio style={radioStyle} value='loop'> 从 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handleLoopChange(e,'minute','start')}/> 分开始,每 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handleLoopChange(e,'minute','end')}/> 分执行一次 </Radio> <Radio style={radioStyle} value='point'> <Checkbox.Group style={{ width: '100%' }} onChange={e => this.handleCheckboxChange(e,'minute')}> 指定 {minuteCheckbox} </Checkbox.Group> </Radio> </Radio.Group> </TabPane> <TabPane tab="时" key="3"> <Radio.Group onChange={e => this.handleRadioChange(e,'hour')} value={radioValue['hour']}> <Radio style={radioStyle} value={1}> 每小时执行 </Radio> <Radio style={radioStyle} value='period'> 周期从 <InputNumber size="small" min={0} max={23} defaultValue={1} onChange={e => this.handlePeriodChange(e,'hour','min')}/> - <InputNumber size="small" min={0} max={23} defaultValue={1} onChange={e => this.handlePeriodChange(e,'hour','max')}/> 时 </Radio> <Radio style={radioStyle} value='loop'> 从 <InputNumber size="small" min={0} max={23} defaultValue={1} onChange={e => this.handleLoopChange(e,'hour','start')}/> 时开始,每 <InputNumber size="small" min={1} max={59} defaultValue={1} onChange={e => this.handleLoopChange(e,'hour','end')}/> 时执行一次 </Radio> <Radio style={radioStyle} value='point'> <Checkbox.Group style={{ width: '100%' }} onChange={e => this.handleCheckboxChange(e,'hour')}> 指定 {hourCheckbox} </Checkbox.Group> </Radio> </Radio.Group> </TabPane> <TabPane tab="日" key="4"> <Radio.Group onChange={e => this.handleRadioChange(e,'day')} value={radioValue['day']}> <Radio style={radioStyle} value={1}> 每日执行 </Radio> <Radio style={radioStyle} value={2}> 不指定 </Radio> <Radio style={radioStyle} value='period'> 周期从 <InputNumber size="small" min={1} max={31} defaultValue={1} onChange={e => this.handlePeriodChange(e,'day','min')}/> - <InputNumber size="small" min={1} max={31} defaultValue={1} onChange={e => this.handlePeriodChange(e,'day','max')}/> 日 </Radio> <Radio style={radioStyle} value='loop'> 从 <InputNumber size="small" min={1} max={31} defaultValue={1} onChange={e => this.handleLoopChange(e,'day','start')}/> 日开始,每 <InputNumber size="small" min={1} max={31} defaultValue={1} onChange={e => this.handleLoopChange(e,'day','end')}/> 日执行一次 </Radio> <Radio style={radioStyle} value='point'> <Checkbox.Group style={{ width: '100%' }} onChange={e => this.handleCheckboxChange(e,'day')}> 指定 {dayCheckbox} </Checkbox.Group> </Radio> </Radio.Group> </TabPane> <TabPane tab="月" key="5"> <Radio.Group onChange={e => this.handleRadioChange(e,'month')} value={radioValue['month']}> <Radio style={radioStyle} value={1}> 每月执行 </Radio> <Radio style={radioStyle} value={2}> 不指定 </Radio> <Radio style={radioStyle} value='period'> 周期从 <InputNumber size="small" min={1} max={12} defaultValue={1} onChange={e => this.handlePeriodChange(e,'month','min')}/> - <InputNumber size="small" min={1} max={12} defaultValue={1} onChange={e => this.handlePeriodChange(e,'month','max')}/> 月 </Radio> <Radio style={radioStyle} value='loop'> 从 <InputNumber size="small" min={1} max={12} defaultValue={1} onChange={e => this.handleLoopChange(e,'month','start')}/> 月开始,每 <InputNumber size="small" min={1} max={12} defaultValue={1} onChange={e => this.handleLoopChange(e,'month','end')}/> 月执行一次 </Radio> <Radio style={radioStyle} value='point'> <Checkbox.Group style={{ width: '100%' }} onChange={e => this.handleCheckboxChange(e,'month')}> 指定 {monthCheckbox} </Checkbox.Group> </Radio> </Radio.Group> </TabPane> <TabPane tab="周" key="6"> <Radio.Group onChange={e => this.handleRadioChange(e,'week')} value={radioValue['week']}> <Radio style={radioStyle} value={1}> 每周执行 </Radio> <Radio style={radioStyle} value={2}> 不指定 </Radio> <Radio style={radioStyle} value='period'> 周期从 周 <InputNumber size="small" min={1} max={7} defaultValue={1} onChange={e => this.handlePeriodChange(e,'week','min')}/> - 周 <InputNumber size="small" min={1} max={7} defaultValue={1} onChange={e => this.handlePeriodChange(e,'week','max')}/> </Radio> <Radio style={radioStyle} value='point'> <Checkbox.Group style={{ width: '100%' }} onChange={e => this.handleCheckboxChange(e,'week')}> 指定 {weekCheckbox} </Checkbox.Group> </Radio> </Radio.Group> </TabPane> </Tabs> <Search placeholder="生成Cron" enterButton="生成" style={{ width: 400,marginTop:10 }} onSearch={this.createCron} value={cronText} /> </> ) } } export default CronGenerator;