cmdb/cmdb-ui/src/components/Crontab/Crontab.vue

409 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div :style="{ width: '490px' }">
<el-tabs type="card" class="ops-crontab">
<el-tab-pane label="" v-if="shouldHide('second')">
<CrontabSecond @update="updateContabValue" :check="checkNumber" ref="cronsecond" />
</el-tab-pane>
<el-tab-pane label="分钟" v-if="shouldHide('min')">
<CrontabMin @update="updateContabValue" :check="checkNumber" :cron="contabValueObj" ref="cronmin" />
</el-tab-pane>
<el-tab-pane label="小时" v-if="shouldHide('hour')">
<CrontabHour @update="updateContabValue" :check="checkNumber" :cron="contabValueObj" ref="cronhour" />
</el-tab-pane>
<el-tab-pane label="" v-if="shouldHide('day')">
<CrontabDay @update="updateContabValue" :check="checkNumber" :cron="contabValueObj" ref="cronday" />
</el-tab-pane>
<el-tab-pane label="" v-if="shouldHide('mouth')">
<CrontabMouth @update="updateContabValue" :check="checkNumber" :cron="contabValueObj" ref="cronmouth" />
</el-tab-pane>
<el-tab-pane label="" v-if="shouldHide('week')">
<CrontabWeek @update="updateContabValue" :check="checkNumber" :cron="contabValueObj" ref="cronweek" />
</el-tab-pane>
<el-tab-pane label="" v-if="shouldHide('year')">
<CrontabYear @update="updateContabValue" :check="checkNumber" :cron="contabValueObj" ref="cronyear" />
</el-tab-pane>
</el-tabs>
<div class="popup-main">
<div class="popup-result">
<p class="title">时间表达式</p>
<div style="padding: 12px;">
<div></div>
<table>
<thead>
<th v-for="item of displayTabTitles" width="40" :key="item.value">{{ item.label }}</th>
<th>crontab完整表达式</th>
</thead>
<tbody>
<td v-if="shouldHide('second')">
<span class="square">{{ contabValueObj.second }}</span>
</td>
<td v-if="shouldHide('min')">
<span class="square">{{ contabValueObj.min }}</span>
</td>
<td v-if="shouldHide('hour')">
<span class="square">{{ contabValueObj.hour }}</span>
</td>
<td v-if="shouldHide('day')">
<span class="square">{{ contabValueObj.day === '?' ? '*' : contabValueObj.day }}</span>
</td>
<td v-if="shouldHide('mouth')">
<span class="square">{{ contabValueObj.mouth }}</span>
</td>
<td v-if="shouldHide('week')">
<span class="square">{{ contabValueObj.week === '?' ? '*' : contabValueObj.week }}</span>
</td>
<td v-if="shouldHide('year')">
<span class="square">{{ contabValueObj.year }}</span>
</td>
<td>
<span class="rectangle">{{ displayContabValueString }}</span>
</td>
</tbody>
</table>
</div>
</div>
<!-- <CrontabResult :ex="contabValueString"></CrontabResult> -->
</div>
<div class="pop_btn" v-if="hasFooter">
<a-space>
<a-button size="small" type="primary" @click="submitFill">确定</a-button>
<a-button size="small" type="warning" @click="clearCron">重置</a-button>
<a-button size="small" @click="hidePopup">取消</a-button>
</a-space>
</div>
</div>
</template>
<script>
/* eslint-disable */
import CrontabSecond from './Crontab-Second.vue'
import CrontabMin from './Crontab-Min.vue'
import CrontabHour from './Crontab-Hour.vue'
import CrontabDay from './Crontab-Day.vue'
import CrontabMouth from './Crontab-Mouth.vue'
import CrontabWeek from './Crontab-Week.vue'
import CrontabYear from './Crontab-Year.vue'
import CrontabResult from './Crontab-Result.vue'
import { cronValidate } from './utils/index'
// 对表达式进行特异化处理 不展示 但是计算的时候还是有
export default {
data() {
return {
tabTitles: [
{ value: 'second', label: '' },
{ value: 'min', label: '分钟' },
{ value: 'hour', label: '小时' },
{ value: 'day', label: '' },
{ value: 'month', label: '' },
{ value: 'week', label: '' },
{ value: 'year', label: '' },
],
tabActive: 0,
myindex: 0,
contabValueObj: {
second: '*',
min: '*',
hour: '*',
day: '*',
mouth: '*',
week: '?',
year: '',
},
}
},
name: 'Vcrontab',
props: ['expression', 'hideComponent', 'defaultExpression', 'hasFooter'],
methods: {
shouldHide(key) {
if (this.hideComponent && this.hideComponent.includes(key)) return false
return true
},
resolveExp(expression) {
// 反解析 表达式
if (expression) {
const arr = expression.split(' ')
if (arr.length >= 6) {
// 6 位以上是合法表达式
const obj = {
second: arr[0],
min: arr[1],
hour: arr[2],
day: arr[3],
mouth: arr[4],
week: arr[5],
year: arr[6] ? arr[6] : '',
}
this.contabValueObj = {
...obj,
}
for (const i in obj) {
if (obj[i]) this.changeRadio(i, obj[i])
}
}
}
},
// tab切换值
tabCheck(index) {
this.tabActive = index
},
// 由子组件触发更改表达式组成的字段值
updateContabValue(name, value, from) {
'updateContabValue', name, value, from
this.$set(this.contabValueObj, name, value)
if (from && from !== name) {
// console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
this.changeRadio(name, value)
}
},
// 赋值到组件
changeRadio(name, value) {
const arr = ['second', 'min', 'hour', 'mouth']
const refName = 'cron' + name
let insVlaue
if (!this.$refs[refName]) return
if (arr.includes(name)) {
if (value === '*') {
insVlaue = 1
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
isNaN(indexArr[0]) ? (this.$refs[refName].cycle01 = 0) : (this.$refs[refName].cycle01 = indexArr[0])
this.$refs[refName].cycle02 = indexArr[1]
insVlaue = 2
} else if (value.indexOf('/') > -1) {
const indexArr = value.split('/')
isNaN(indexArr[0]) ? (this.$refs[refName].average01 = 0) : (this.$refs[refName].average01 = indexArr[0])
this.$refs[refName].average02 = indexArr[1]
insVlaue = 3
} else {
insVlaue = 4
this.$refs[refName].checkboxList = value.split(',').map((v) => Number(v))
}
} else if (name == 'day') {
if (value === '*') {
insVlaue = 1
} else if (value == '?') {
insVlaue = 2
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
isNaN(indexArr[0]) ? (this.$refs[refName].cycle01 = 0) : (this.$refs[refName].cycle01 = indexArr[0])
this.$refs[refName].cycle02 = indexArr[1]
insVlaue = 3
} else if (value.indexOf('/') > -1) {
const indexArr = value.split('/')
isNaN(indexArr[0]) ? (this.$refs[refName].average01 = 0) : (this.$refs[refName].average01 = indexArr[0])
this.$refs[refName].average02 = indexArr[1]
insVlaue = 4
} else if (value.indexOf('W') > -1) {
const indexArr = value.split('W')
isNaN(indexArr[0]) ? (this.$refs[refName].workday = 0) : (this.$refs[refName].workday = indexArr[0])
insVlaue = 5
} else if (value === 'L') {
insVlaue = 6
} else {
this.$refs[refName].checkboxList = value.split(',')
insVlaue = 7
}
} else if (name == 'week') {
if (value === '*') {
insVlaue = 1
} else if (value == '?') {
insVlaue = 2
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
isNaN(indexArr[0]) ? (this.$refs[refName].cycle01 = 0) : (this.$refs[refName].cycle01 = indexArr[0])
this.$refs[refName].cycle02 = indexArr[1]
insVlaue = 3
} else if (value.indexOf('#') > -1) {
const indexArr = value.split('#')
isNaN(indexArr[0]) ? (this.$refs[refName].average01 = 1) : (this.$refs[refName].average01 = indexArr[0])
this.$refs[refName].average02 = indexArr[1]
insVlaue = 4
} else if (value.indexOf('L') > -1) {
const indexArr = value.split('L')
isNaN(indexArr[0]) ? (this.$refs[refName].weekday = 1) : (this.$refs[refName].weekday = indexArr[0])
insVlaue = 5
} else {
this.$refs[refName].checkboxList = value.split(',')
insVlaue = 6
}
} else if (name == 'year') {
if (value == '') {
insVlaue = 1
} else if (value == '*') {
insVlaue = 2
} else if (value.indexOf('-') > -1) {
insVlaue = 3
} else if (value.indexOf('/') > -1) {
insVlaue = 4
} else {
this.$refs[refName].checkboxList = value.split(',')
insVlaue = 5
}
}
this.$refs[refName].radioValue = insVlaue
},
// 表单选项的子组件校验数字格式通过-props传递
checkNumber(value, minLimit, maxLimit) {
// 检查必须为整数
value = Math.floor(value)
if (value < minLimit) {
value = minLimit
} else if (value > maxLimit) {
value = maxLimit
}
return value
},
// 隐藏弹窗
hidePopup() {
this.$emit('hide')
},
// 填充表达式
submitFill() {
const result = cronValidate(this.contabValueString)
console.log(result)
if (typeof result !== 'boolean') {
this.$message.warning(result)
return this.$emit('error', result)
}
this.$emit('fill', this.displayContabValueString)
this.hidePopup()
},
clearCron() {
// 还原选择项
this.resolveExp(this.defaultExpression || '* * * * * ?')
},
},
computed: {
contabValueString: function() {
const obj = this.contabValueObj
const str =
obj.second +
' ' +
obj.min +
' ' +
obj.hour +
' ' +
obj.day +
' ' +
obj.mouth +
' ' +
obj.week +
(obj.year == '' ? '' : ' ' + obj.year)
return str
},
displayContabValueString() {
//去掉第一位秒改成 * 仅作展示用
const _temp = this.contabValueString.substring(2)
const reg = /\?/g
return _temp.replace(reg, '*')
},
displayTabTitles() {
return this.tabTitles.filter((item) => !this.hideComponent.includes(item.value))
},
},
components: {
CrontabSecond,
CrontabMin,
CrontabHour,
CrontabDay,
CrontabMouth,
CrontabWeek,
CrontabYear,
CrontabResult,
},
watch: {
expression: {
handler(val) {
if (!val) {
this.clearCron()
return
}
this.resolveExp(val)
},
immediate: true,
},
},
mounted() {
// 初始化
if (this.expression) {
this.resolveExp(this.expression)
} else {
this.clearCron()
}
},
}
</script>
<style lang="less" scoped>
.pop_btn {
text-align: right;
margin-top: 24px;
}
.popup-main {
position: relative;
margin: 16px auto;
background: #fff;
border-radius: 8px;
font-size: 12px;
overflow: hidden;
box-shadow: 0px 8px 16px rgba(160, 181, 235, 0.25);
}
.popup-title {
overflow: hidden;
line-height: 34px;
padding-top: 6px;
background: #f2f2f2;
}
.popup-result {
border-radius: 8px;
}
.popup-result .title {
background: #fff;
font-weight: 400;
font-size: 14px;
color: #2f54eb;
background-color: #f0f5ff;
margin: 0px;
box-sizing: border-box;
padding-left: 12px;
}
.popup-result table {
text-align: center;
width: 100%;
margin: 0 auto;
}
.popup-result table span {
display: block;
width: 100%;
font-family: arial;
line-height: 26px;
height: 26px;
white-space: nowrap;
overflow: hidden;
border: 1px solid #e8e8e8;
border-radius: 4px;
}
.popup-result table span.square {
width: 40px;
box-sizing: border-box;
}
.popup-result table span.rectangle {
width: 247px;
}
.popup-result-scroll {
font-size: 12px;
line-height: 24px;
height: 10em;
overflow-y: auto;
}
</style>