UNPKG

cron-editor-react

Version:

基于antd、react的crontab表达式生成工具

616 lines (588 loc) 23 kB
/** * 功能:主界面 * 作者:宋鑫鑫 * 日期:2019.11.04 */ import React, { PureComponent } from "react"; import PropTypes from 'prop-types' import { Tabs, Dropdown, Row, Col, Input, List, Collapse } from "antd"; import Year from "./components/Year"; import Month from "./components/Month"; import Week from "./components/Week"; import Day from "./components/Day"; import Hour from "./components/Hour"; import Minute from "./components/Minute"; import Second from "./components/Second"; import CronParse from "./parse-lib/index"; import CronParser from "cron-parser"; import moment from "moment"; const { TabPane } = Tabs; const { Panel } = Collapse; import "./css/index.less"; const noop = function () { } const dateMinute = "YYYY-MM-DD HH:mm"; class Cron extends PureComponent { constructor(props) { super(props); const date = new Date(); this.state = { activeKey: "second", year: { type: "", start: date.getFullYear(), end: date.getFullYear() }, month: { start: 1, end: 2, begin: 1, beginEvery: 1, type: "*", some: ['1'] }, week: { start: 1, end: 2, last: 1, begin: 1, beginEvery: 1, type: "?", some: [1] }, day: { last: 1, closeWorkDay: 1, start: 1, end: 2, begin: 1, beginEvery: 1, type: "*", some: ['1'] }, hour: { start: 0, end: 1, begin: 0, beginEvery: 1, type: "*", some: ['0'] }, minute: { start: 0, end: 1, begin: 0, beginEvery: 1, type: "*", some: ['0'] }, second: { start: 0, end: 1, begin: 0, beginEvery: 1, type: "*", some: ['0'] }, runTime: [] }; } initValue() { let { value } = this.props value = value.toUpperCase() const valuesArray = value.split(" "); let newState = { ...this.state }; newState.second.value = valuesArray[0] || ""; newState.minute.value = valuesArray[1] || ""; newState.hour.value = valuesArray[2] || ""; newState.day.value = valuesArray[3] || ""; newState.month.value = valuesArray[4] || ""; newState.week.value = valuesArray[5] || ""; newState.year.value = valuesArray[6] || ""; this.setState(newState, () => { this.parse(); }); } componentDidMount(props) { this.initValue(props); } componentDidUpdate(props) { const { value } = this.props if (props.value !== value && value) { this.initValue(); } } parse() { let { year, month, week, day, hour, minute, second } = this.state; if (year.value.indexOf("-") > -1) { year.type = "period"; const period = year.value.split("-")[0]; year.start = period[0]; year.end = period[1]; } else { year.type = year.value; } if (week.value.indexOf("-") > -1) { week.type = "period"; const period = week.value.split("-")[0]; week.start = period[0]; week.end = period[1]; } else if (week.value.indexOf("L") > -1) { week.type = "last"; week.last = week.value.split("L")[0] || 1; } else if (week.value.indexOf("#") > -1) { week.type = "beginInterval"; week.begin = week.value.split("#")[0]; week.beginEvery = week.value.split("#")[1]; } else if (week.value.indexOf(",") > -1 || /^[0-9]+$/.test(week.value)) { week.type = "some"; week.some = week.value.split(","); } else { week.type = week.value || "?"; } if (month.value.indexOf("-") > -1) { month.type = "period"; month.start = month.value.split("-")[0]; month.end = month.value.split("-")[1]; } else if (month.value.indexOf("/") > -1) { month.type = "beginInterval"; month.begin = month.value.split("/")[0]; month.beginEvery = month.value.split("/")[1]; } else if (month.value.indexOf(",") > -1 || /^[0-9]+$/.test(month.value)) { month.type = "some"; month.some = month.value.split(","); } else { month.type = month.value || "?"; } if (day.value.indexOf("-") > -1) { day.type = "period"; day.start = day.value.split("-")[0]; day.end = day.value.split("-")[1]; } else if (day.value.indexOf("W") > -1) { day.type = "closeWorkDay"; day.closeWorkDay = day.value.split("W")[0] || 1; } else if (day.value.indexOf("L") > -1) { day.type = "last"; day.last = day.value.split("L")[0] || 1; } else if (day.value.indexOf("/") > -1) { day.type = "beginInterval"; day.begin = day.value.split("/")[0]; day.beginEvery = day.value.split("/")[1]; } else if (day.value.indexOf(",") > -1 || /^[0-9]+$/.test(day.value)) { day.type = "some"; day.some = day.value.split(","); } else { day.type = day.value || "?"; } if (hour.value.indexOf("-") > -1) { hour.type = "period"; hour.start = hour.value.split("-")[0]; hour.end = hour.value.split("-")[1]; } else if (hour.value.indexOf("/") > -1) { hour.type = "beginInterval"; hour.begin = hour.value.split("/")[0]; hour.beginEvery = hour.value.split("/")[1]; } else if (hour.value.indexOf(",") > -1 || /^[0-9]+$/.test(hour.value)) { hour.type = "some"; hour.some = hour.value.split(","); } else { hour.type = hour.value || "?"; } if (minute.value.indexOf("-") > -1) { minute.type = "period"; minute.start = minute.value.split("-")[0]; minute.end = minute.value.split("-")[1]; } else if (minute.value.indexOf("/") > -1) { minute.type = "beginInterval"; minute.begin = minute.value.split("/")[0]; minute.beginEvery = minute.value.split("/")[1]; } else if (minute.value.indexOf(",") > -1 || /^[0-9]+$/.test(minute.value)) { minute.type = "some"; minute.some = minute.value.split(","); } else { minute.type = minute.value || "?"; } if (second.value.indexOf("-") > -1) { second.type = "period"; second.start = second.value.split("-")[0]; second.end = second.value.split("-")[1]; } else if (second.value.indexOf("/") > -1) { second.type = "beginInterval"; second.begin = second.value.split("/")[0]; second.beginEvery = second.value.split("/")[1]; } else if (second.value.indexOf(",") > -1 || /^[0-9]+$/.test(second.value)) { second.type = "some"; second.some = second.value.split(","); } else { second.type = second.value || "?"; } this.setState({ year: { ...year }, month: { ...month }, week: { ...week }, day: { ...day }, hour: { ...hour }, minute: { ...minute }, second: { ...second } }); console.log("this.state :", this.state); } format() { const { year, month, week, day, hour, minute, second } = this.state; return `${second.value} ${minute.value} ${hour.value} ${day.value} ${month.value} ${week.value} ${year.value}`; } changeState(state) { this.setState(state, () => { this.culcCron(); }); } // 计算用户的cron culcCron() { const { n2s } = this; let { year, month, week, day, hour, minute, second } = this.state; if (year.type === "period") { year.value = `${n2s(year.start)}-${n2s(year.end)}`; } else { year.value = year.type; } if (month.type === "period") { month.value = `${n2s(month.start)}-${n2s(month.end)}`; } else if (month.type === "beginInterval") { month.value = `${n2s(month.begin)}/${n2s(month.beginEvery)}`; } else if (month.type === "some") { month.value = month.some.join(","); } else { month.value = month.type; } if (week.type === "period") { week.value = `${n2s(week.start)}-${n2s(week.end)}`; } else if (week.type === "beginInterval") { week.value = `${n2s(week.begin)}#${n2s(week.beginEvery)}`; } else if (week.type === "last") { week.value = n2s(week.last) + "L"; } else if (week.type === "some") { week.value = week.some.join(","); } else { week.value = week.type; } if (day.type === "period") { day.value = `${n2s(day.start)}-${n2s(day.end)}`; } else if (day.type === "beginInterval") { day.value = `${n2s(day.begin)}/${n2s(day.beginEvery)}`; } else if (day.type === "closeWorkDay") { day.value = n2s(day.closeWorkDay || 1) + "W"; } else if (day.type === "last") { // day.value = n2s(day.last || 1) + "L"; day.value = "L"; } else if (day.type === "some") { day.value = day.some.join(","); } else { day.value = day.type; } if (hour.type === "period") { hour.value = `${n2s(hour.start)}-${n2s(hour.end)}`; } else if (hour.type === "beginInterval") { hour.value = `${n2s(hour.begin)}/${n2s(hour.beginEvery)}`; } else if (hour.type === "some") { hour.value = hour.some.join(","); } else { hour.value = hour.type; } if (minute.type === "period") { minute.value = `${n2s(minute.start)}-${n2s(minute.end)}`; } else if (minute.type === "beginInterval") { minute.value = `${n2s(minute.begin)}/${n2s(minute.beginEvery)}`; } else if (minute.type === "some") { minute.value = minute.some.join(","); } else { minute.value = minute.type; } if (second.type === "period") { second.value = `${n2s(second.start)}-${n2s(second.end)}`; } else if (second.type === "beginInterval") { second.value = `${n2s(second.begin)}/${n2s(second.beginEvery)}`; } else if (second.type === "some") { second.value = second.some.join(","); } else { second.value = second.type; } this.setState( { year: { ...year }, month: { ...month }, week: { ...week }, day: { ...day }, hour: { ...hour }, minute: { ...minute }, second: { ...second } }, () => { this.triggerChange(); } ); } n2s(number) { if (typeof number === "number" && number !== NaN) { return `${number}`; } return number; } triggerChange() { const { onChange, showRunTime } = this.props const crontab = this.format(); console.log('crontab', crontab) onChange && onChange(crontab); if (!showRunTime) return; // 既然不需要,那就不算了 let tempArr = []; const weekCron = crontab.split(" ")[5]; try { if (weekCron !== "?") { const interval = CronParser.parseExpression(String(crontab).trim()); for (let i = 0; i < 5; i++) { const temp = moment(interval.next().toString()).format(dateMinute); tempArr.push(temp); } } else { const cron = new CronParse(); tempArr = cron.expressionChange(String(crontab).trim()); } } catch (error) { // console.log("error :", error); tempArr.push("暂无最新执行周期"); } if (tempArr.length > 0) { this.setState({ runTime: tempArr }); } } // 发生表单值改变,重新计算 onChange = (type, value) => { this.state[type].value = value; this.setState({ ...this.state }, () => { this.parse(); }); }; renderOverLay() { const { activeKey, week, day } = this.state; const { tabType } = this.props return ( <Tabs activeKey={activeKey} onChange={key => { this.setState({ activeKey: key }); }} type={tabType} > <TabPane tab="秒" key="second"> <Second {...this.state} onChange={state => { this.changeState({ second: state }); }} /> </TabPane> <TabPane tab="分钟" key="minute"> <Minute {...this.state} onChange={state => { this.changeState({ minute: state }); }} /> </TabPane> <TabPane tab="小时" key="hour"> <Hour {...this.state} onChange={state => { this.changeState({ hour: state }); }} /> </TabPane> <TabPane tab="日" key="day"> <Day {...this.state} onChange={state => { if (week.type === '?' && state.type === '?') { const obj = { ...week, type: "*" } console.log('obj', obj) this.setState({ week: obj }) } else { const obj = { ...week, type: "?" } console.log('obj', obj) this.setState({ week: obj }) } this.changeState({ day: state }); }} /> </TabPane> <TabPane tab="月" key="month"> <Month {...this.state} onChange={state => { this.changeState({ month: state }); }} /> </TabPane> <TabPane tab="周" key="week"> <Week {...this.state} onChange={state => { if (day.type === '?' && state.type === '?') { const obj = { ...week, type: "*" } console.log('obj', obj) this.setState({ day: obj }) } else { const obj = { ...week, type: "?" } console.log('obj', obj) this.setState({ day: obj }) } this.changeState({ week: state }); }} /> </TabPane> <TabPane tab="年" key="year"> <Year {...this.state} onChange={state => { this.changeState({ year: state }); }} /> </TabPane> </Tabs> ); } render() { const state = JSON.parse(JSON.stringify(this.state)); const { year, month, week, day, hour, minute, second, runTime } = state; const { showRunTime, showCrontab } = this.props return ( <div className="cron-editor-react"> {this.renderOverLay()} { showCrontab && ( <List bordered style={{ marginTop: 10 }} > <List.Item className="cron-list-type"> <Row type="flex" gutter={5} style={{ width: "100%", textAlign: "center" }}> <Col span={3}></Col> <Col span={3}></Col> <Col span={3}>小时</Col> <Col span={3}></Col> <Col span={3}></Col> <Col span={3}>星期</Col> <Col span={3}></Col> </Row> </List.Item> <List.Item> <Row type="flex" gutter={5} style={{ width: "100%", textAlign: "center" }}> <Col span={3}> <Input value={second.value} onChange={e => { this.onChange("second", e.target.value); }} disabled /> </Col> <Col span={3}> <Input value={minute.value} onChange={e => { this.onChange("minute", e.target.value); }} disabled /> </Col> <Col span={3}> <Input value={hour.value} onChange={e => { this.onChange("hour", e.target.value); }} disabled /> </Col> <Col span={3}> <Input value={day.value} onChange={e => { this.onChange("day", e.target.value); }} disabled /> </Col> <Col span={3}> <Input value={month.value} onChange={e => { this.onChange("month", e.target.value); }} disabled /> </Col> <Col span={3}> <Input value={week.value} onChange={e => { this.onChange("week", e.target.value); }} disabled /> </Col> <Col span={3}> <Input value={year.value} onChange={e => { this.onChange("year", e.target.value); }} disabled /> </Col> </Row> </List.Item> </List> ) } { showRunTime && ( <Collapse> <Panel header="近5次执行时间" key="1"> <List bordered dataSource={runTime} renderItem={(item, index) => ( <List.Item> 第{index + 1}执行时间: {item} </List.Item> )} /> </Panel> </Collapse> ) } </div> ); } } Cron.propTypes = { onChange: PropTypes.func, showRunTime: PropTypes.bool, value: PropTypes.string, tabType: PropTypes.string, showCrontab: PropTypes.bool } Cron.defaultProps = { onChange: noop, showRunTime: false, value: '0 0 0 * * ?', tabType: 'line', showCrontab: true } export default Cron;