|
|
package com.idormy.sms.forwarder.fragment.condition
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
import android.content.Intent
|
|
|
import android.text.Editable
|
|
|
import android.text.TextWatcher
|
|
|
import android.util.Log
|
|
|
import android.view.LayoutInflater
|
|
|
import android.view.View
|
|
|
import android.view.ViewGroup
|
|
|
import android.widget.LinearLayout
|
|
|
import android.widget.RadioGroup
|
|
|
import com.google.gson.Gson
|
|
|
import com.idormy.sms.forwarder.R
|
|
|
import com.idormy.sms.forwarder.core.BaseFragment
|
|
|
import com.idormy.sms.forwarder.databinding.FragmentTasksConditionCronBinding
|
|
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
|
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
|
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_CONDITION
|
|
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
|
|
import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION
|
|
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CRON
|
|
|
import com.idormy.sms.forwarder.utils.XToastUtils
|
|
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
|
|
import com.xuexiang.xaop.annotation.SingleClick
|
|
|
import com.xuexiang.xpage.annotation.Page
|
|
|
import com.xuexiang.xrouter.annotation.AutoWired
|
|
|
import com.xuexiang.xrouter.launcher.XRouter
|
|
|
import com.xuexiang.xui.utils.CountDownButtonHelper
|
|
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
|
|
import com.xuexiang.xui.widget.flowlayout.FlowTagLayout
|
|
|
import gatewayapps.crondroid.CronExpression
|
|
|
import net.redhogs.cronparser.CronExpressionDescriptor
|
|
|
import net.redhogs.cronparser.Options
|
|
|
import java.text.SimpleDateFormat
|
|
|
import java.util.Date
|
|
|
import java.util.Locale
|
|
|
|
|
|
@Page(name = "Cron")
|
|
|
@Suppress("PrivatePropertyName")
|
|
|
class CronFragment : BaseFragment<FragmentTasksConditionCronBinding?>(), View.OnClickListener {
|
|
|
|
|
|
private val TAG: String = CronFragment::class.java.simpleName
|
|
|
private var titleBar: TitleBar? = null
|
|
|
private var mCountDownHelper: CountDownButtonHelper? = null
|
|
|
|
|
|
@JvmField
|
|
|
@AutoWired(name = KEY_EVENT_DATA_CONDITION)
|
|
|
var eventData: String? = null
|
|
|
|
|
|
private val secondsList: List<String> = (0..59).map { String.format("%02d", it) }
|
|
|
private var selectedSecondList = ""
|
|
|
|
|
|
private val minutesList: List<String> = (0..59).map { String.format("%02d", it) }
|
|
|
private var selectedMinuteList = ""
|
|
|
|
|
|
private val hoursList: List<String> = (0..23).map { String.format("%02d", it) }
|
|
|
private var selectedHourList = ""
|
|
|
|
|
|
private val dayList: List<String> = (1..31).map { String.format("%d", it) }
|
|
|
private var selectedDayList = ""
|
|
|
|
|
|
//private val monthList = listOf("JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC")
|
|
|
private val monthList: List<String> = (1..12).map { String.format("%d", it) }
|
|
|
private var selectedMonthList = ""
|
|
|
|
|
|
//private val weekList = listOf("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN")
|
|
|
private val weekList: List<String> = (1..7).map { String.format("%d", it) }
|
|
|
private var selectedWeekList = ""
|
|
|
|
|
|
private val yearList: List<String> = (2020..2099).map { String.format("%d", it) }
|
|
|
private var selectedYearList = ""
|
|
|
|
|
|
private var second = "*"
|
|
|
private var minute = "*"
|
|
|
private var hour = "*"
|
|
|
private var day = "*"
|
|
|
private var month = "*"
|
|
|
private var week = "?"
|
|
|
private var year = "*"
|
|
|
private var expression = "$second $minute $hour $day $month $week $year"
|
|
|
private var description = ""
|
|
|
|
|
|
override fun initArgs() {
|
|
|
XRouter.getInstance().inject(this)
|
|
|
}
|
|
|
|
|
|
override fun viewBindingInflate(
|
|
|
inflater: LayoutInflater,
|
|
|
container: ViewGroup,
|
|
|
): FragmentTasksConditionCronBinding {
|
|
|
return FragmentTasksConditionCronBinding.inflate(inflater, container, false)
|
|
|
}
|
|
|
|
|
|
override fun initTitle(): TitleBar? {
|
|
|
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_cron)
|
|
|
return titleBar
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 初始化控件
|
|
|
*/
|
|
|
override fun initViews() {
|
|
|
//测试按钮增加倒计时,避免重复点击
|
|
|
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
|
|
|
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
|
|
|
override fun onCountDown(time: Int) {
|
|
|
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
|
|
|
}
|
|
|
|
|
|
override fun onFinished() {
|
|
|
binding!!.btnTest.text = getString(R.string.test)
|
|
|
}
|
|
|
})
|
|
|
|
|
|
Log.d(TAG, "initViews eventData:$eventData")
|
|
|
if (eventData != null) {
|
|
|
val settingVo = Gson().fromJson(eventData, CronSetting::class.java)
|
|
|
binding!!.tvDescription.text = settingVo.description
|
|
|
expression = settingVo.expression
|
|
|
Log.d(TAG, "initViews expression:$expression")
|
|
|
|
|
|
val fields = expression.split(" ")
|
|
|
second = fields.getOrNull(0) ?: "*"
|
|
|
minute = fields.getOrNull(1) ?: "*"
|
|
|
hour = fields.getOrNull(2) ?: "*"
|
|
|
day = fields.getOrNull(3) ?: "*"
|
|
|
month = fields.getOrNull(4) ?: "*"
|
|
|
week = fields.getOrNull(5) ?: "?"
|
|
|
year = fields.getOrNull(6) ?: "*"
|
|
|
}
|
|
|
|
|
|
//初始化输入提示
|
|
|
initSecondInputHelper()
|
|
|
initMinuteInputHelper()
|
|
|
initHourInputHelper()
|
|
|
initDayInputHelper()
|
|
|
initMonthInputHelper()
|
|
|
initWeekInputHelper()
|
|
|
initYearInputHelper()
|
|
|
}
|
|
|
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
override fun initListeners() {
|
|
|
binding!!.btnTest.setOnClickListener(this)
|
|
|
binding!!.btnDel.setOnClickListener(this)
|
|
|
binding!!.btnSave.setOnClickListener(this)
|
|
|
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) {
|
|
|
mCountDownHelper?.finish()
|
|
|
switchInputHelper(binding!!.layoutCronExpressionCheck)
|
|
|
if (it == "success") {
|
|
|
//生成最近10次运行时间
|
|
|
val nextTimeList = mutableListOf<String>()
|
|
|
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
|
|
val cronExpression = CronExpression(expression)
|
|
|
var nextDate = Date()
|
|
|
var times = 0
|
|
|
for (i in 0 until 10) {
|
|
|
nextDate = cronExpression.getNextValidTimeAfter(nextDate) ?: break
|
|
|
nextTimeList.add(dateFormat.format(nextDate))
|
|
|
times++
|
|
|
}
|
|
|
binding!!.tvDescription.text = description
|
|
|
binding!!.tvCronExpressionCheckTips.text = "$expression\n$description"
|
|
|
binding!!.tvNextTimeList.text = String.format(getString(R.string.next_execution_times), times.toString(), nextTimeList.joinToString("\n"))
|
|
|
binding!!.tvNextTimeList.visibility = View.VISIBLE
|
|
|
binding!!.separatorCronExpressionCheck.visibility = View.VISIBLE
|
|
|
} else {
|
|
|
binding!!.tvCronExpressionCheckTips.text = String.format(getString(R.string.invalid_cron_expression), it.toString())
|
|
|
binding!!.tvNextTimeList.text = ""
|
|
|
binding!!.tvNextTimeList.visibility = View.GONE
|
|
|
binding!!.separatorCronExpressionCheck.visibility = View.GONE
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@SingleClick
|
|
|
override fun onClick(v: View) {
|
|
|
try {
|
|
|
when (v.id) {
|
|
|
R.id.btn_test -> {
|
|
|
mCountDownHelper?.start()
|
|
|
Thread {
|
|
|
try {
|
|
|
val settingVo = checkSetting()
|
|
|
Log.d(TAG, settingVo.toString())
|
|
|
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post("success")
|
|
|
} catch (e: Exception) {
|
|
|
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post(e.message.toString())
|
|
|
e.printStackTrace()
|
|
|
}
|
|
|
}.start()
|
|
|
return
|
|
|
}
|
|
|
|
|
|
R.id.btn_del -> {
|
|
|
popToBack()
|
|
|
return
|
|
|
}
|
|
|
|
|
|
R.id.btn_save -> {
|
|
|
val settingVo = checkSetting()
|
|
|
val intent = Intent()
|
|
|
intent.putExtra(KEY_BACK_DESCRIPTION_CONDITION, description)
|
|
|
intent.putExtra(KEY_BACK_DATA_CONDITION, Gson().toJson(settingVo))
|
|
|
setFragmentResult(TASK_CONDITION_CRON, intent)
|
|
|
popToBack()
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error(e.message.toString(), 30000)
|
|
|
e.printStackTrace()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//切换输入提示
|
|
|
private fun switchInputHelper(layout: LinearLayout) {
|
|
|
binding!!.layoutSecondType.visibility = View.GONE
|
|
|
binding!!.layoutMinuteType.visibility = View.GONE
|
|
|
binding!!.layoutHourType.visibility = View.GONE
|
|
|
binding!!.layoutDayType.visibility = View.GONE
|
|
|
binding!!.layoutMonthType.visibility = View.GONE
|
|
|
binding!!.layoutWeekType.visibility = View.GONE
|
|
|
binding!!.layoutYearType.visibility = View.GONE
|
|
|
binding!!.layoutCronExpressionCheck.visibility = View.GONE
|
|
|
layout.visibility = View.VISIBLE
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--秒
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun initSecondInputHelper() {
|
|
|
binding!!.etSecond.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutSecondType)
|
|
|
} else {
|
|
|
afterSecondChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etSecond.setText(second)
|
|
|
afterSecondChanged()
|
|
|
|
|
|
//秒类型
|
|
|
binding!!.rgSecondType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_second_type_cyclic -> {
|
|
|
var secondCyclicFrom = binding!!.etSecondCyclicFrom.text.toString().trim()
|
|
|
if (secondCyclicFrom.isEmpty()) {
|
|
|
secondCyclicFrom = "00"
|
|
|
binding!!.etSecondCyclicFrom.setText(secondCyclicFrom)
|
|
|
}
|
|
|
var secondCyclicTo = binding!!.etSecondCyclicTo.text.toString().trim()
|
|
|
if (secondCyclicTo.isEmpty()) {
|
|
|
secondCyclicTo = "59"
|
|
|
binding!!.etSecondCyclicTo.setText(secondCyclicTo)
|
|
|
}
|
|
|
second = "$secondCyclicFrom-$secondCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_second_type_interval -> {
|
|
|
var secondIntervalStart = binding!!.etSecondIntervalStart.text.toString().trim()
|
|
|
if (secondIntervalStart.isEmpty()) {
|
|
|
secondIntervalStart = "0"
|
|
|
binding!!.etSecondIntervalStart.setText(secondIntervalStart)
|
|
|
}
|
|
|
var secondInterval = binding!!.etSecondInterval.text.toString().trim()
|
|
|
if (secondInterval.isEmpty()) {
|
|
|
secondInterval = "2"
|
|
|
binding!!.etSecondInterval.setText(secondInterval)
|
|
|
}
|
|
|
second = "$secondIntervalStart/$secondInterval"
|
|
|
}
|
|
|
|
|
|
R.id.rb_second_type_assigned -> {
|
|
|
if (selectedSecondList.isEmpty()) {
|
|
|
selectedSecondList = "00"
|
|
|
binding!!.flowlayoutMultiSelectSecond.setSelectedItems("00")
|
|
|
}
|
|
|
second = selectedSecondList
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
second = "*"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etSecond.setText(second)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--秒--周期
|
|
|
val secondCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val secondCyclicFrom = binding!!.etSecondCyclicFrom.text.toString().trim()
|
|
|
val secondCyclicTo = binding!!.etSecondCyclicTo.text.toString().trim()
|
|
|
if (secondCyclicFrom.isNotEmpty() && secondCyclicTo.isNotEmpty()) {
|
|
|
second = "$secondCyclicFrom-$secondCyclicTo"
|
|
|
binding!!.etSecond.setText(second)
|
|
|
binding!!.rbSecondTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etSecondCyclicFrom.addTextChangedListener(secondCyclicWatcher)
|
|
|
binding!!.etSecondCyclicTo.addTextChangedListener(secondCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--秒--间隔
|
|
|
val secondIntervalWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val secondIntervalStart = binding!!.etSecondIntervalStart.text.toString().trim()
|
|
|
val secondInterval = binding!!.etSecondInterval.text.toString().trim()
|
|
|
if (secondIntervalStart.isNotEmpty() && secondInterval.isNotEmpty()) {
|
|
|
second = "$secondIntervalStart/$secondInterval"
|
|
|
binding!!.etSecond.setText(second)
|
|
|
binding!!.rbSecondTypeInterval.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etSecondIntervalStart.addTextChangedListener(secondIntervalWatcher)
|
|
|
binding!!.etSecondInterval.addTextChangedListener(secondIntervalWatcher)
|
|
|
|
|
|
//初始化输入提示--秒--指定
|
|
|
binding!!.flowlayoutMultiSelectSecond.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectSecond.setItems(secondsList)
|
|
|
binding!!.flowlayoutMultiSelectSecond.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedSecondList = getSelectedItems(parent, selectedList, 1)
|
|
|
Log.d(TAG, "position:$position, selectedSecondList:$selectedSecondList")
|
|
|
if (selectedSecondList.isEmpty()) {
|
|
|
binding!!.rbSecondTypeAll.isChecked = true
|
|
|
second = "*"
|
|
|
} else {
|
|
|
binding!!.rbSecondTypeAssigned.isChecked = true
|
|
|
second = selectedSecondList
|
|
|
}
|
|
|
binding!!.etSecond.setText(second)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private fun afterSecondChanged() {
|
|
|
second = binding!!.etSecond.text.toString().trim()
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterSecondChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
second == "*" -> {
|
|
|
binding!!.rbSecondTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
second.contains("/") -> {
|
|
|
val secondsArray = second.split("/")
|
|
|
binding!!.etSecondIntervalStart.setText(secondsArray.getOrNull(0) ?: "0")
|
|
|
binding!!.etSecondInterval.setText(secondsArray.getOrNull(1) ?: "1")
|
|
|
binding!!.rbSecondTypeInterval.isChecked = true
|
|
|
}
|
|
|
|
|
|
second.contains(",") -> {
|
|
|
val secondsList = restoreMergedItems(second, "%02d")
|
|
|
Log.d(TAG, "secondsList:$secondsList")
|
|
|
binding!!.flowlayoutMultiSelectSecond.setSelectedItems(secondsList)
|
|
|
binding!!.rbSecondTypeAssigned.isChecked = true
|
|
|
selectedSecondList = secondsList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
second.contains("-") -> {
|
|
|
val secondsArray = second.split("-")
|
|
|
binding!!.etSecondCyclicFrom.setText(secondsArray.getOrNull(0) ?: "00")
|
|
|
binding!!.etSecondCyclicTo.setText(secondsArray.getOrNull(1) ?: "59")
|
|
|
binding!!.rbSecondTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
secondsList.indexOf(String.format("%02d", second.toInt())) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectSecond.setSelectedItems(String.format("%02d", second.toInt()))
|
|
|
binding!!.rbSecondTypeAssigned.isChecked = true
|
|
|
selectedSecondList = second
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbSecondTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--分
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun initMinuteInputHelper() {
|
|
|
binding!!.etMinute.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutMinuteType)
|
|
|
} else {
|
|
|
afterMinuteChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etMinute.setText(minute)
|
|
|
afterMinuteChanged()
|
|
|
|
|
|
//分类型
|
|
|
binding!!.rgMinuteType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_minute_type_cyclic -> {
|
|
|
var minuteCyclicFrom = binding!!.etMinuteCyclicFrom.text.toString().trim()
|
|
|
if (minuteCyclicFrom.isEmpty()) {
|
|
|
minuteCyclicFrom = "00"
|
|
|
binding!!.etMinuteCyclicFrom.setText(minuteCyclicFrom)
|
|
|
}
|
|
|
var minuteCyclicTo = binding!!.etMinuteCyclicTo.text.toString().trim()
|
|
|
if (minuteCyclicTo.isEmpty()) {
|
|
|
minuteCyclicTo = "59"
|
|
|
binding!!.etMinuteCyclicTo.setText(minuteCyclicTo)
|
|
|
}
|
|
|
minute = "$minuteCyclicFrom-$minuteCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_minute_type_interval -> {
|
|
|
var minuteIntervalStart = binding!!.etMinuteIntervalStart.text.toString().trim()
|
|
|
if (minuteIntervalStart.isEmpty()) {
|
|
|
minuteIntervalStart = "0"
|
|
|
binding!!.etMinuteIntervalStart.setText(minuteIntervalStart)
|
|
|
}
|
|
|
var minuteInterval = binding!!.etMinuteInterval.text.toString().trim()
|
|
|
if (minuteInterval.isEmpty()) {
|
|
|
minuteInterval = "2"
|
|
|
binding!!.etMinuteInterval.setText(minuteInterval)
|
|
|
}
|
|
|
minute = "$minuteIntervalStart/$minuteInterval"
|
|
|
}
|
|
|
|
|
|
R.id.rb_minute_type_assigned -> {
|
|
|
if (selectedMinuteList.isEmpty()) {
|
|
|
selectedMinuteList = "00"
|
|
|
binding!!.flowlayoutMultiSelectMinute.setSelectedItems("00")
|
|
|
}
|
|
|
minute = selectedMinuteList
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
minute = "*"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etMinute.setText(minute)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--分--周期
|
|
|
val minuteCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val minuteCyclicFrom = binding!!.etMinuteCyclicFrom.text.toString().trim()
|
|
|
val minuteCyclicTo = binding!!.etMinuteCyclicTo.text.toString().trim()
|
|
|
if (minuteCyclicFrom.isNotEmpty() && minuteCyclicTo.isNotEmpty()) {
|
|
|
minute = "$minuteCyclicFrom-$minuteCyclicTo"
|
|
|
binding!!.etMinute.setText(minute)
|
|
|
binding!!.rbMinuteTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etMinuteCyclicFrom.addTextChangedListener(minuteCyclicWatcher)
|
|
|
binding!!.etMinuteCyclicTo.addTextChangedListener(minuteCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--分--间隔
|
|
|
val minuteIntervalWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val minuteIntervalStart = binding!!.etMinuteIntervalStart.text.toString().trim()
|
|
|
val minuteInterval = binding!!.etMinuteInterval.text.toString().trim()
|
|
|
if (minuteIntervalStart.isNotEmpty() && minuteInterval.isNotEmpty()) {
|
|
|
minute = "$minuteIntervalStart/$minuteInterval"
|
|
|
binding!!.etMinute.setText(minute)
|
|
|
binding!!.rbMinuteTypeInterval.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etMinuteIntervalStart.addTextChangedListener(minuteIntervalWatcher)
|
|
|
binding!!.etMinuteInterval.addTextChangedListener(minuteIntervalWatcher)
|
|
|
|
|
|
//初始化输入提示--分--指定
|
|
|
binding!!.flowlayoutMultiSelectMinute.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectMinute.setItems(minutesList)
|
|
|
binding!!.flowlayoutMultiSelectMinute.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedMinuteList = getSelectedItems(parent, selectedList, 1)
|
|
|
Log.d(TAG, "position:$position, selectedMinutesList:$selectedMinuteList")
|
|
|
if (selectedMinuteList.isEmpty()) {
|
|
|
binding!!.rbMinuteTypeAll.isChecked = true
|
|
|
minute = "*"
|
|
|
} else {
|
|
|
binding!!.rbMinuteTypeAssigned.isChecked = true
|
|
|
minute = selectedMinuteList
|
|
|
}
|
|
|
binding!!.etMinute.setText(minute)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private fun afterMinuteChanged() {
|
|
|
minute = binding!!.etMinute.text.toString().trim()
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterMinuteChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
minute == "*" -> {
|
|
|
binding!!.rbMinuteTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
minute.contains("/") -> {
|
|
|
val minutesArray = minute.split("/")
|
|
|
binding!!.etMinuteIntervalStart.setText(minutesArray.getOrNull(0) ?: "0")
|
|
|
binding!!.etMinuteInterval.setText(minutesArray.getOrNull(1) ?: "1")
|
|
|
binding!!.rbMinuteTypeInterval.isChecked = true
|
|
|
}
|
|
|
|
|
|
minute.contains(",") -> {
|
|
|
val minutesList = restoreMergedItems(minute, "%02d")
|
|
|
Log.d(TAG, "minutesList:$minutesList")
|
|
|
binding!!.flowlayoutMultiSelectMinute.setSelectedItems(minutesList)
|
|
|
binding!!.rbMinuteTypeAssigned.isChecked = true
|
|
|
selectedMinuteList = minutesList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
minute.contains("-") -> {
|
|
|
val minutesArray = minute.split("-")
|
|
|
binding!!.etMinuteCyclicFrom.setText(minutesArray.getOrNull(0) ?: "00")
|
|
|
binding!!.etMinuteCyclicTo.setText(minutesArray.getOrNull(1) ?: "59")
|
|
|
binding!!.rbMinuteTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
minutesList.indexOf(String.format("%02d", minute.toInt())) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectMinute.setSelectedItems(String.format("%02d", minute.toInt()))
|
|
|
binding!!.rbMinuteTypeAssigned.isChecked = true
|
|
|
selectedMinuteList = minute
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbMinuteTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--时
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun initHourInputHelper() {
|
|
|
binding!!.etHour.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutHourType)
|
|
|
} else {
|
|
|
afterHourChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etHour.setText(hour)
|
|
|
afterHourChanged()
|
|
|
|
|
|
//时类型
|
|
|
binding!!.rgHourType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_hour_type_cyclic -> {
|
|
|
var hourCyclicFrom = binding!!.etHourCyclicFrom.text.toString().trim()
|
|
|
if (hourCyclicFrom.isEmpty()) {
|
|
|
hourCyclicFrom = "00"
|
|
|
binding!!.etHourCyclicFrom.setText(hourCyclicFrom)
|
|
|
}
|
|
|
var hourCyclicTo = binding!!.etHourCyclicTo.text.toString().trim()
|
|
|
if (hourCyclicTo.isEmpty()) {
|
|
|
hourCyclicTo = "23"
|
|
|
binding!!.etHourCyclicTo.setText(hourCyclicTo)
|
|
|
}
|
|
|
hour = "$hourCyclicFrom-$hourCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_hour_type_interval -> {
|
|
|
var hourIntervalStart = binding!!.etHourIntervalStart.text.toString().trim()
|
|
|
if (hourIntervalStart.isEmpty()) {
|
|
|
hourIntervalStart = "0"
|
|
|
binding!!.etHourIntervalStart.setText(hourIntervalStart)
|
|
|
}
|
|
|
var hourInterval = binding!!.etHourInterval.text.toString().trim()
|
|
|
if (hourInterval.isEmpty()) {
|
|
|
hourInterval = "2"
|
|
|
binding!!.etHourInterval.setText(hourInterval)
|
|
|
}
|
|
|
hour = "$hourIntervalStart/$hourInterval"
|
|
|
}
|
|
|
|
|
|
R.id.rb_hour_type_assigned -> {
|
|
|
if (selectedHourList.isEmpty()) {
|
|
|
selectedHourList = "00"
|
|
|
binding!!.flowlayoutMultiSelectHour.setSelectedItems("00")
|
|
|
}
|
|
|
hour = selectedHourList
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
hour = "*"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etHour.setText(hour)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--时--周期
|
|
|
val hourCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val hourCyclicFrom = binding!!.etHourCyclicFrom.text.toString().trim()
|
|
|
val hourCyclicTo = binding!!.etHourCyclicTo.text.toString().trim()
|
|
|
if (hourCyclicFrom.isNotEmpty() && hourCyclicTo.isNotEmpty()) {
|
|
|
hour = "$hourCyclicFrom-$hourCyclicTo"
|
|
|
binding!!.etHour.setText(hour)
|
|
|
binding!!.rbHourTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etHourCyclicFrom.addTextChangedListener(hourCyclicWatcher)
|
|
|
binding!!.etHourCyclicTo.addTextChangedListener(hourCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--时--间隔
|
|
|
val hourIntervalWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val hourIntervalStart = binding!!.etHourIntervalStart.text.toString().trim()
|
|
|
val hourInterval = binding!!.etHourInterval.text.toString().trim()
|
|
|
if (hourIntervalStart.isNotEmpty() && hourInterval.isNotEmpty()) {
|
|
|
hour = "$hourIntervalStart/$hourInterval"
|
|
|
binding!!.etHour.setText(hour)
|
|
|
binding!!.rbHourTypeInterval.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etHourIntervalStart.addTextChangedListener(hourIntervalWatcher)
|
|
|
binding!!.etHourInterval.addTextChangedListener(hourIntervalWatcher)
|
|
|
|
|
|
//初始化输入提示--时--指定
|
|
|
binding!!.flowlayoutMultiSelectHour.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectHour.setItems(hoursList)
|
|
|
binding!!.flowlayoutMultiSelectHour.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedHourList = getSelectedItems(parent, selectedList, 1)
|
|
|
Log.d(TAG, "position:$position, selectedHoursList:$selectedHourList")
|
|
|
if (selectedHourList.isEmpty()) {
|
|
|
binding!!.rbHourTypeAll.isChecked = true
|
|
|
hour = "*"
|
|
|
} else {
|
|
|
binding!!.rbHourTypeAssigned.isChecked = true
|
|
|
hour = selectedHourList
|
|
|
}
|
|
|
binding!!.etHour.setText(hour)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private fun afterHourChanged() {
|
|
|
hour = binding!!.etHour.text.toString().trim()
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterHourChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
hour == "*" -> {
|
|
|
binding!!.rbHourTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
hour.contains("/") -> {
|
|
|
val hoursArray = hour.split("/")
|
|
|
binding!!.etHourIntervalStart.setText(hoursArray.getOrNull(0) ?: "0")
|
|
|
binding!!.etHourInterval.setText(hoursArray.getOrNull(1) ?: "1")
|
|
|
binding!!.rbHourTypeInterval.isChecked = true
|
|
|
}
|
|
|
|
|
|
hour.contains(",") -> {
|
|
|
val hoursList = restoreMergedItems(hour, "%02d")
|
|
|
Log.d(TAG, "hoursList:$hoursList")
|
|
|
binding!!.flowlayoutMultiSelectHour.setSelectedItems(hoursList)
|
|
|
binding!!.rbHourTypeAssigned.isChecked = true
|
|
|
selectedHourList = hoursList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
hour.contains("-") -> {
|
|
|
val hoursArray = hour.split("-")
|
|
|
binding!!.etHourCyclicFrom.setText(hoursArray.getOrNull(0) ?: "00")
|
|
|
binding!!.etHourCyclicTo.setText(hoursArray.getOrNull(1) ?: "23")
|
|
|
binding!!.rbHourTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
hoursList.indexOf(String.format("%02d", hour.toInt())) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectHour.setSelectedItems(String.format("%02d", hour.toInt()))
|
|
|
binding!!.rbHourTypeAssigned.isChecked = true
|
|
|
selectedHourList = hour
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbHourTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--日
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun initDayInputHelper() {
|
|
|
binding!!.etDay.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutDayType)
|
|
|
} else {
|
|
|
afterDayChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etDay.setText(day)
|
|
|
afterDayChanged()
|
|
|
|
|
|
//日类型
|
|
|
binding!!.rgDayType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_day_type_cyclic -> {
|
|
|
var dayCyclicFrom = binding!!.etDayCyclicFrom.text.toString().trim()
|
|
|
if (dayCyclicFrom.isEmpty()) {
|
|
|
dayCyclicFrom = "1"
|
|
|
binding!!.etDayCyclicFrom.setText(dayCyclicFrom)
|
|
|
}
|
|
|
var dayCyclicTo = binding!!.etDayCyclicTo.text.toString().trim()
|
|
|
if (dayCyclicTo.isEmpty()) {
|
|
|
dayCyclicTo = "31"
|
|
|
binding!!.etDayCyclicTo.setText(dayCyclicTo)
|
|
|
}
|
|
|
day = "$dayCyclicFrom-$dayCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_day_type_interval -> {
|
|
|
var dayIntervalStart = binding!!.etDayIntervalStart.text.toString().trim()
|
|
|
if (dayIntervalStart.isEmpty()) {
|
|
|
dayIntervalStart = "1"
|
|
|
binding!!.etDayIntervalStart.setText(dayIntervalStart)
|
|
|
}
|
|
|
var dayInterval = binding!!.etDayInterval.text.toString().trim()
|
|
|
if (dayInterval.isEmpty()) {
|
|
|
dayInterval = "2"
|
|
|
binding!!.etDayInterval.setText(dayInterval)
|
|
|
}
|
|
|
day = "$dayIntervalStart/$dayInterval"
|
|
|
}
|
|
|
|
|
|
R.id.rb_day_type_assigned -> {
|
|
|
if (selectedDayList.isEmpty()) {
|
|
|
selectedDayList = "1"
|
|
|
binding!!.flowlayoutMultiSelectDay.setSelectedItems("1")
|
|
|
}
|
|
|
day = selectedDayList
|
|
|
}
|
|
|
|
|
|
R.id.rb_day_type_last_day_of_month -> {
|
|
|
day = "L"
|
|
|
}
|
|
|
|
|
|
R.id.rb_day_type_last_day_of_month_recent_day -> {
|
|
|
day = "LW"
|
|
|
}
|
|
|
|
|
|
R.id.rb_day_type_recent_day -> {
|
|
|
var recentDay = binding!!.etRecentDay.text.toString().trim()
|
|
|
if (recentDay.isEmpty()) {
|
|
|
recentDay = "1"
|
|
|
binding!!.etRecentDay.setText(recentDay)
|
|
|
}
|
|
|
day = recentDay + "W"
|
|
|
}
|
|
|
|
|
|
R.id.rb_day_type_not_assigned -> {
|
|
|
day = "?"
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
day = "*"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etDay.setText(day)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--日--周期
|
|
|
val dayCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val dayCyclicFrom = binding!!.etDayCyclicFrom.text.toString().trim()
|
|
|
val dayCyclicTo = binding!!.etDayCyclicTo.text.toString().trim()
|
|
|
if (dayCyclicFrom.isNotEmpty() && dayCyclicTo.isNotEmpty()) {
|
|
|
day = "$dayCyclicFrom-$dayCyclicTo"
|
|
|
binding!!.etDay.setText(day)
|
|
|
binding!!.rbDayTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etDayCyclicFrom.addTextChangedListener(dayCyclicWatcher)
|
|
|
binding!!.etDayCyclicTo.addTextChangedListener(dayCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--日--间隔
|
|
|
val dayIntervalWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val dayIntervalStart = binding!!.etDayIntervalStart.text.toString().trim()
|
|
|
val dayInterval = binding!!.etDayInterval.text.toString().trim()
|
|
|
if (dayIntervalStart.isNotEmpty() && dayInterval.isNotEmpty()) {
|
|
|
day = "$dayIntervalStart/$dayInterval"
|
|
|
binding!!.etDay.setText(day)
|
|
|
binding!!.rbDayTypeInterval.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etDayIntervalStart.addTextChangedListener(dayIntervalWatcher)
|
|
|
binding!!.etDayInterval.addTextChangedListener(dayIntervalWatcher)
|
|
|
|
|
|
//初始化输入提示--日--指定
|
|
|
binding!!.flowlayoutMultiSelectDay.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectDay.setItems(dayList)
|
|
|
binding!!.flowlayoutMultiSelectDay.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedDayList = getSelectedItems(parent, selectedList)
|
|
|
Log.d(TAG, "position:$position, selectedDayList:$selectedDayList")
|
|
|
if (selectedDayList.isEmpty()) {
|
|
|
binding!!.rbDayTypeAll.isChecked = true
|
|
|
day = "*"
|
|
|
} else {
|
|
|
binding!!.rbDayTypeAssigned.isChecked = true
|
|
|
day = selectedDayList
|
|
|
}
|
|
|
binding!!.etDay.setText(day)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private fun afterDayChanged() {
|
|
|
//周和日不能同时设置
|
|
|
day = binding!!.etDay.text.toString().trim()
|
|
|
if (day != "?" && week != "?") {
|
|
|
week = "?"
|
|
|
binding!!.etWeek.setText(week)
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterDayChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
day == "*" -> {
|
|
|
binding!!.rbDayTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
day == "?" -> {
|
|
|
binding!!.rbDayTypeNotAssigned.isChecked = true
|
|
|
}
|
|
|
|
|
|
day == "L" -> {
|
|
|
binding!!.rbDayTypeLastDayOfMonth.isChecked = true
|
|
|
}
|
|
|
|
|
|
day == "LW" -> {
|
|
|
binding!!.rbDayTypeLastDayOfMonthRecentDay.isChecked = true
|
|
|
return
|
|
|
}
|
|
|
|
|
|
day.endsWith("W") -> {
|
|
|
binding!!.rbDayTypeRecentDay.isChecked = true
|
|
|
binding!!.etRecentDay.setText(day.removeSuffix("W"))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
day.contains("/") -> {
|
|
|
val dayArray = day.split("/")
|
|
|
binding!!.etDayIntervalStart.setText(dayArray.getOrNull(0) ?: "0")
|
|
|
binding!!.etDayInterval.setText(dayArray.getOrNull(1) ?: "1")
|
|
|
binding!!.rbDayTypeInterval.isChecked = true
|
|
|
}
|
|
|
|
|
|
day.contains(",") -> {
|
|
|
val dayList = restoreMergedItems(day, "%d")
|
|
|
Log.d(TAG, "dayList:$dayList")
|
|
|
binding!!.flowlayoutMultiSelectDay.setSelectedItems(dayList)
|
|
|
binding!!.rbDayTypeAssigned.isChecked = true
|
|
|
selectedDayList = dayList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
day.contains("-") -> {
|
|
|
val dayArray = day.split("-")
|
|
|
binding!!.etDayCyclicFrom.setText(dayArray.getOrNull(0) ?: "1")
|
|
|
binding!!.etDayCyclicTo.setText(dayArray.getOrNull(1) ?: "31")
|
|
|
binding!!.rbDayTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
dayList.indexOf(String.format("%d", day.toInt())) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectDay.setSelectedItems(String.format("%d", day.toInt()))
|
|
|
binding!!.rbDayTypeAssigned.isChecked = true
|
|
|
selectedDayList = day
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbDayTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--月
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun initMonthInputHelper() {
|
|
|
binding!!.etMonth.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutMonthType)
|
|
|
} else {
|
|
|
afterMonthChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etMonth.setText(month)
|
|
|
afterMonthChanged()
|
|
|
|
|
|
//月类型
|
|
|
binding!!.rgMonthType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_month_type_cyclic -> {
|
|
|
var monthCyclicFrom = binding!!.etMonthCyclicFrom.text.toString().trim()
|
|
|
if (monthCyclicFrom.isEmpty()) {
|
|
|
monthCyclicFrom = "1"
|
|
|
binding!!.etMonthCyclicFrom.setText(monthCyclicFrom)
|
|
|
}
|
|
|
var monthCyclicTo = binding!!.etMonthCyclicTo.text.toString().trim()
|
|
|
if (monthCyclicTo.isEmpty()) {
|
|
|
monthCyclicTo = "12"
|
|
|
binding!!.etMonthCyclicTo.setText(monthCyclicTo)
|
|
|
}
|
|
|
month = "$monthCyclicFrom-$monthCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_month_type_interval -> {
|
|
|
var monthIntervalStart = binding!!.etMonthIntervalStart.text.toString().trim()
|
|
|
if (monthIntervalStart.isEmpty()) {
|
|
|
monthIntervalStart = "1"
|
|
|
binding!!.etMonthIntervalStart.setText(monthIntervalStart)
|
|
|
}
|
|
|
var monthInterval = binding!!.etMonthInterval.text.toString().trim()
|
|
|
if (monthInterval.isEmpty()) {
|
|
|
monthInterval = "2"
|
|
|
binding!!.etMonthInterval.setText(monthInterval)
|
|
|
}
|
|
|
month = "$monthIntervalStart/$monthInterval"
|
|
|
}
|
|
|
|
|
|
R.id.rb_month_type_assigned -> {
|
|
|
if (selectedMonthList.isEmpty()) {
|
|
|
selectedMonthList = "1"
|
|
|
binding!!.flowlayoutMultiSelectMonth.setSelectedItems("1")
|
|
|
}
|
|
|
month = selectedMonthList
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
month = "*"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etMonth.setText(month)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--月--周期
|
|
|
val monthCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val monthCyclicFrom = binding!!.etMonthCyclicFrom.text.toString().trim()
|
|
|
val monthCyclicTo = binding!!.etMonthCyclicTo.text.toString().trim()
|
|
|
if (monthCyclicFrom.isNotEmpty() && monthCyclicTo.isNotEmpty()) {
|
|
|
month = "$monthCyclicFrom-$monthCyclicTo"
|
|
|
binding!!.etMonth.setText(month)
|
|
|
binding!!.rbMonthTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etMonthCyclicFrom.addTextChangedListener(monthCyclicWatcher)
|
|
|
binding!!.etMonthCyclicTo.addTextChangedListener(monthCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--月--间隔
|
|
|
val monthIntervalWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val monthIntervalStart = binding!!.etMonthIntervalStart.text.toString().trim()
|
|
|
val monthInterval = binding!!.etMonthInterval.text.toString().trim()
|
|
|
if (monthIntervalStart.isNotEmpty() && monthInterval.isNotEmpty()) {
|
|
|
month = "$monthIntervalStart/$monthInterval"
|
|
|
binding!!.etMonth.setText(month)
|
|
|
binding!!.rbMonthTypeInterval.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etMonthIntervalStart.addTextChangedListener(monthIntervalWatcher)
|
|
|
binding!!.etMonthInterval.addTextChangedListener(monthIntervalWatcher)
|
|
|
|
|
|
//初始化输入提示--月--指定
|
|
|
binding!!.flowlayoutMultiSelectMonth.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectMonth.setItems(monthList)
|
|
|
binding!!.flowlayoutMultiSelectMonth.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedMonthList = getSelectedItems(parent, selectedList)
|
|
|
Log.d(TAG, "position:$position, selectedMonthList:$selectedMonthList")
|
|
|
if (selectedMonthList.isEmpty()) {
|
|
|
binding!!.rbMonthTypeAll.isChecked = true
|
|
|
month = "*"
|
|
|
} else {
|
|
|
binding!!.rbMonthTypeAssigned.isChecked = true
|
|
|
month = selectedMonthList
|
|
|
}
|
|
|
binding!!.etMonth.setText(month)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private fun afterMonthChanged() {
|
|
|
month = binding!!.etMonth.text.toString().trim()
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterMonthChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
month == "*" -> {
|
|
|
binding!!.rbMonthTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
month.contains("/") -> {
|
|
|
val monthArray = month.split("/")
|
|
|
binding!!.etMonthIntervalStart.setText(monthArray.getOrNull(0) ?: "0")
|
|
|
binding!!.etMonthInterval.setText(monthArray.getOrNull(1) ?: "1")
|
|
|
binding!!.rbMonthTypeInterval.isChecked = true
|
|
|
}
|
|
|
|
|
|
month.contains(",") -> {
|
|
|
val monthList = restoreMergedItems(month, "%d")
|
|
|
Log.d(TAG, "monthList:$monthList")
|
|
|
binding!!.flowlayoutMultiSelectMonth.setSelectedItems(monthList)
|
|
|
binding!!.rbMonthTypeAssigned.isChecked = true
|
|
|
selectedMonthList = monthList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
month.contains("-") -> {
|
|
|
val monthArray = month.split("-")
|
|
|
binding!!.etMonthCyclicFrom.setText(monthArray.getOrNull(0) ?: "1")
|
|
|
binding!!.etMonthCyclicTo.setText(monthArray.getOrNull(1) ?: "31")
|
|
|
binding!!.rbMonthTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
monthList.indexOf(month) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectMonth.setSelectedItems(month)
|
|
|
binding!!.rbMonthTypeAssigned.isChecked = true
|
|
|
selectedMonthList = month
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbMonthTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--周
|
|
|
private fun initWeekInputHelper() {
|
|
|
binding!!.etWeek.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutWeekType)
|
|
|
} else {
|
|
|
afterWeekChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etWeek.setText(week)
|
|
|
afterWeekChanged()
|
|
|
|
|
|
//周类型
|
|
|
binding!!.rgWeekType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_week_type_cyclic -> {
|
|
|
var weekCyclicFrom = binding!!.etWeekCyclicFrom.text.toString().trim()
|
|
|
if (weekCyclicFrom.isEmpty()) {
|
|
|
weekCyclicFrom = "1"
|
|
|
binding!!.etWeekCyclicFrom.setText(weekCyclicFrom)
|
|
|
}
|
|
|
var weekCyclicTo = binding!!.etWeekCyclicTo.text.toString().trim()
|
|
|
if (weekCyclicTo.isEmpty()) {
|
|
|
weekCyclicTo = "7"
|
|
|
binding!!.etWeekCyclicTo.setText(weekCyclicTo)
|
|
|
}
|
|
|
week = "$weekCyclicFrom-$weekCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_week_type_weeks_of_week -> {
|
|
|
var whichWeekOfMonth = binding!!.etWhichWeekOfMonth.text.toString().trim()
|
|
|
if (whichWeekOfMonth.isEmpty()) {
|
|
|
whichWeekOfMonth = "1"
|
|
|
binding!!.etWhichWeekOfMonth.setText(whichWeekOfMonth)
|
|
|
}
|
|
|
var whichDayOfWeek = binding!!.etWhichDayOfWeek.text.toString().trim()
|
|
|
if (whichDayOfWeek.isEmpty()) {
|
|
|
whichDayOfWeek = "1"
|
|
|
binding!!.etWhichDayOfWeek.setText(whichDayOfWeek)
|
|
|
}
|
|
|
week = "$whichWeekOfMonth#$whichDayOfWeek"
|
|
|
}
|
|
|
|
|
|
R.id.rb_week_type_assigned -> {
|
|
|
if (selectedWeekList.isEmpty()) {
|
|
|
selectedWeekList = "1"
|
|
|
binding!!.flowlayoutMultiSelectWeek.setSelectedItems("1")
|
|
|
}
|
|
|
week = selectedWeekList
|
|
|
}
|
|
|
|
|
|
R.id.rb_week_type_last_week_of_month -> {
|
|
|
var lastWeekOfMonth = binding!!.etLastWeekOfMonth.text.toString().trim()
|
|
|
if (lastWeekOfMonth.isEmpty()) {
|
|
|
lastWeekOfMonth = "1"
|
|
|
binding!!.etLastWeekOfMonth.setText(lastWeekOfMonth)
|
|
|
}
|
|
|
week = lastWeekOfMonth + "L"
|
|
|
}
|
|
|
|
|
|
R.id.rb_week_type_all -> {
|
|
|
week = "*"
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
week = "?"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etWeek.setText(week)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--周--周期
|
|
|
val weekCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val weekCyclicFrom = binding!!.etWeekCyclicFrom.text.toString().trim()
|
|
|
val weekCyclicTo = binding!!.etWeekCyclicTo.text.toString().trim()
|
|
|
if (weekCyclicFrom.isNotEmpty() && weekCyclicTo.isNotEmpty()) {
|
|
|
week = "$weekCyclicFrom-$weekCyclicTo"
|
|
|
binding!!.etWeek.setText(week)
|
|
|
binding!!.rbWeekTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etWeekCyclicFrom.addTextChangedListener(weekCyclicWatcher)
|
|
|
binding!!.etWeekCyclicTo.addTextChangedListener(weekCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--周--间隔
|
|
|
val weeksOfWeekWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val whichWeekOfMonth = binding!!.etWhichWeekOfMonth.text.toString().trim()
|
|
|
val whichDayOfWeek = binding!!.etWhichDayOfWeek.text.toString().trim()
|
|
|
if (whichWeekOfMonth.isNotEmpty() && whichDayOfWeek.isNotEmpty()) {
|
|
|
week = "$whichWeekOfMonth#$whichDayOfWeek"
|
|
|
binding!!.etWeek.setText(week)
|
|
|
binding!!.rbWeekTypeWeeksOfWeek.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etWhichWeekOfMonth.addTextChangedListener(weeksOfWeekWatcher)
|
|
|
binding!!.etWhichDayOfWeek.addTextChangedListener(weeksOfWeekWatcher)
|
|
|
|
|
|
//初始化输入提示--周--指定
|
|
|
binding!!.flowlayoutMultiSelectWeek.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectWeek.setItems(weekList)
|
|
|
binding!!.flowlayoutMultiSelectWeek.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedWeekList = getSelectedItems(parent, selectedList)
|
|
|
Log.d(TAG, "position:$position, selectedWeekList:$selectedWeekList")
|
|
|
if (selectedWeekList.isEmpty()) {
|
|
|
binding!!.rbWeekTypeAll.isChecked = true
|
|
|
week = "?"
|
|
|
} else {
|
|
|
binding!!.rbWeekTypeAssigned.isChecked = true
|
|
|
week = selectedWeekList
|
|
|
}
|
|
|
binding!!.etWeek.setText(week)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--周--本月最后
|
|
|
binding!!.etLastWeekOfMonth.addTextChangedListener(object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val lastWeekOfMonth = binding!!.etLastWeekOfMonth.text.toString().trim()
|
|
|
if (lastWeekOfMonth.isNotEmpty()) {
|
|
|
week = lastWeekOfMonth + "L"
|
|
|
binding!!.etWeek.setText(week)
|
|
|
binding!!.rbWeekTypeLastWeekOfMonth.isChecked = true
|
|
|
} else {
|
|
|
week = "*"
|
|
|
binding!!.rbWeekTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
private fun afterWeekChanged() {
|
|
|
//周和日不能同时设置
|
|
|
week = binding!!.etWeek.text.toString().trim()
|
|
|
if (day != "?" && week != "?") {
|
|
|
day = "?"
|
|
|
binding!!.etDay.setText(day)
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterWeekChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
week == "*" -> {
|
|
|
binding!!.rbWeekTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
week == "?" -> {
|
|
|
binding!!.rbWeekTypeNotAssigned.isChecked = true
|
|
|
}
|
|
|
|
|
|
week.contains(",") -> {
|
|
|
val weekList = restoreMergedItems(week, "%d")
|
|
|
Log.d(TAG, "weekList:$weekList")
|
|
|
binding!!.flowlayoutMultiSelectWeek.setSelectedItems(weekList)
|
|
|
binding!!.rbWeekTypeAssigned.isChecked = true
|
|
|
selectedWeekList = weekList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
week.contains("-") -> {
|
|
|
val weekArray = week.split("-")
|
|
|
binding!!.etWeekCyclicFrom.setText(weekArray.getOrNull(0) ?: "1")
|
|
|
binding!!.etWeekCyclicTo.setText(weekArray.getOrNull(1) ?: "31")
|
|
|
binding!!.rbWeekTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
week.contains("#") -> {
|
|
|
val weekArray = week.split("#")
|
|
|
binding!!.etWhichWeekOfMonth.setText(weekArray.getOrNull(0) ?: "1")
|
|
|
binding!!.etWhichDayOfWeek.setText(weekArray.getOrNull(1) ?: "1")
|
|
|
binding!!.rbWeekTypeWeeksOfWeek.isChecked = true
|
|
|
}
|
|
|
|
|
|
weekList.indexOf(week) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectWeek.setSelectedItems(week)
|
|
|
binding!!.rbWeekTypeAssigned.isChecked = true
|
|
|
selectedWeekList = week
|
|
|
}
|
|
|
|
|
|
week.endsWith("L") -> {
|
|
|
binding!!.rbWeekTypeLastWeekOfMonth.isChecked = true
|
|
|
binding!!.etLastWeekOfMonth.setText(week.removeSuffix("L"))
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbWeekTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--年
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun initYearInputHelper() {
|
|
|
binding!!.etYear.setOnFocusChangeListener { _, hasFocus ->
|
|
|
if (hasFocus) {
|
|
|
switchInputHelper(binding!!.layoutYearType)
|
|
|
} else {
|
|
|
afterYearChanged()
|
|
|
}
|
|
|
}
|
|
|
binding!!.etYear.setText(year)
|
|
|
afterYearChanged()
|
|
|
|
|
|
//年类型
|
|
|
binding!!.rgYearType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
|
|
when (checkedId) {
|
|
|
R.id.rb_year_type_cyclic -> {
|
|
|
var yearCyclicFrom = binding!!.etYearCyclicFrom.text.toString().trim()
|
|
|
if (yearCyclicFrom.isEmpty()) {
|
|
|
yearCyclicFrom = "2023"
|
|
|
binding!!.etYearCyclicFrom.setText(yearCyclicFrom)
|
|
|
}
|
|
|
var yearCyclicTo = binding!!.etYearCyclicTo.text.toString().trim()
|
|
|
if (yearCyclicTo.isEmpty()) {
|
|
|
yearCyclicTo = "2058"
|
|
|
binding!!.etYearCyclicTo.setText(yearCyclicTo)
|
|
|
}
|
|
|
year = "$yearCyclicFrom-$yearCyclicTo"
|
|
|
}
|
|
|
|
|
|
R.id.rb_year_type_interval -> {
|
|
|
var yearIntervalStart = binding!!.etYearIntervalStart.text.toString().trim()
|
|
|
if (yearIntervalStart.isEmpty()) {
|
|
|
yearIntervalStart = "2023"
|
|
|
binding!!.etYearIntervalStart.setText(yearIntervalStart)
|
|
|
}
|
|
|
var yearInterval = binding!!.etYearInterval.text.toString().trim()
|
|
|
if (yearInterval.isEmpty()) {
|
|
|
yearInterval = "2"
|
|
|
binding!!.etYearInterval.setText(yearInterval)
|
|
|
}
|
|
|
year = "$yearIntervalStart/$yearInterval"
|
|
|
}
|
|
|
|
|
|
R.id.rb_year_type_assigned -> {
|
|
|
if (selectedYearList.isEmpty()) {
|
|
|
selectedYearList = "1"
|
|
|
binding!!.flowlayoutMultiSelectYear.setSelectedItems("1")
|
|
|
}
|
|
|
year = selectedYearList
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
year = "*"
|
|
|
}
|
|
|
}
|
|
|
binding!!.etYear.setText(year)
|
|
|
}
|
|
|
|
|
|
//初始化输入提示--年--周期
|
|
|
val yearCyclicWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val yearCyclicFrom = binding!!.etYearCyclicFrom.text.toString().trim()
|
|
|
val yearCyclicTo = binding!!.etYearCyclicTo.text.toString().trim()
|
|
|
if (yearCyclicFrom.isNotEmpty() && yearCyclicTo.isNotEmpty()) {
|
|
|
year = "$yearCyclicFrom-$yearCyclicTo"
|
|
|
binding!!.etYear.setText(year)
|
|
|
binding!!.rbYearTypeCyclic.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etYearCyclicFrom.addTextChangedListener(yearCyclicWatcher)
|
|
|
binding!!.etYearCyclicTo.addTextChangedListener(yearCyclicWatcher)
|
|
|
|
|
|
//初始化输入提示--年--间隔
|
|
|
val yearIntervalWatcher = object : TextWatcher {
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
val yearIntervalStart = binding!!.etYearIntervalStart.text.toString().trim()
|
|
|
val yearInterval = binding!!.etYearInterval.text.toString().trim()
|
|
|
if (yearIntervalStart.isNotEmpty() && yearInterval.isNotEmpty()) {
|
|
|
year = "$yearIntervalStart/$yearInterval"
|
|
|
binding!!.etYear.setText(year)
|
|
|
binding!!.rbYearTypeInterval.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
|
|
}
|
|
|
binding!!.etYearIntervalStart.addTextChangedListener(yearIntervalWatcher)
|
|
|
binding!!.etYearInterval.addTextChangedListener(yearIntervalWatcher)
|
|
|
|
|
|
//初始化输入提示--年--指定
|
|
|
binding!!.flowlayoutMultiSelectYear.setTagCheckedMode(FlowTagLayout.FLOW_TAG_CHECKED_MULTI)
|
|
|
binding!!.flowlayoutMultiSelectYear.setItems(yearList)
|
|
|
binding!!.flowlayoutMultiSelectYear.setOnTagSelectListener { parent, position, selectedList ->
|
|
|
selectedYearList = getSelectedItems(parent, selectedList)
|
|
|
Log.d(TAG, "position:$position, selectedYearList:$selectedYearList")
|
|
|
if (selectedYearList.isEmpty()) {
|
|
|
binding!!.rbYearTypeAll.isChecked = true
|
|
|
year = "*"
|
|
|
} else {
|
|
|
binding!!.rbYearTypeAssigned.isChecked = true
|
|
|
year = selectedYearList
|
|
|
}
|
|
|
binding!!.etYear.setText(year)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private fun afterYearChanged() {
|
|
|
year = binding!!.etYear.text.toString().trim()
|
|
|
try {
|
|
|
//判断cronExpression是否有效
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
Log.d(TAG, "afterYearChanged expression:$expression")
|
|
|
CronExpression.validateExpression(expression)
|
|
|
} catch (e: Exception) {
|
|
|
XToastUtils.error("Cron表达式无效:" + e.message, 30000)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
when {
|
|
|
year == "*" -> {
|
|
|
binding!!.rbYearTypeAll.isChecked = true
|
|
|
}
|
|
|
|
|
|
year == "?" -> {
|
|
|
binding!!.rbYearTypeNotAssigned.isChecked = true
|
|
|
}
|
|
|
|
|
|
year.contains("/") -> {
|
|
|
val yearArray = year.split("/")
|
|
|
binding!!.etYearIntervalStart.setText(yearArray.getOrNull(0) ?: "2023")
|
|
|
binding!!.etYearInterval.setText(yearArray.getOrNull(1) ?: "2")
|
|
|
binding!!.rbYearTypeInterval.isChecked = true
|
|
|
}
|
|
|
|
|
|
year.contains(",") -> {
|
|
|
val yearList = restoreMergedItems(year, "%d")
|
|
|
Log.d(TAG, "yearList:$yearList")
|
|
|
binding!!.flowlayoutMultiSelectYear.setSelectedItems(yearList)
|
|
|
binding!!.rbYearTypeAssigned.isChecked = true
|
|
|
selectedYearList = yearList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
year.contains("-") -> {
|
|
|
val yearArray = year.split("-")
|
|
|
binding!!.etYearCyclicFrom.setText(yearArray.getOrNull(0) ?: "1970")
|
|
|
binding!!.etYearCyclicTo.setText(yearArray.getOrNull(1) ?: "2099")
|
|
|
binding!!.rbYearTypeCyclic.isChecked = true
|
|
|
}
|
|
|
|
|
|
yearList.indexOf(year) != -1 -> {
|
|
|
binding!!.flowlayoutMultiSelectYear.setSelectedItems(year)
|
|
|
binding!!.rbYearTypeAssigned.isChecked = true
|
|
|
selectedYearList = year
|
|
|
}
|
|
|
|
|
|
else -> {
|
|
|
binding!!.rbYearTypeAll.isChecked = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//获取选中的项目
|
|
|
private fun getSelectedItems(parent: FlowTagLayout, selectedList: List<Int>, dataType: Int = 0): String {
|
|
|
if (selectedList.isEmpty()) return ""
|
|
|
|
|
|
val selectedNumList = mutableListOf<String>()
|
|
|
for (index in selectedList) {
|
|
|
selectedNumList.add(parent.adapter.getItem(index).toString())
|
|
|
}
|
|
|
val mergedList = when (dataType) {
|
|
|
2 -> mergeContinuousEnum(selectedNumList)
|
|
|
1 -> mergeContinuousItems(selectedNumList, "%02d")
|
|
|
else -> mergeContinuousItems(selectedNumList)
|
|
|
}
|
|
|
return mergedList.joinToString(",")
|
|
|
}
|
|
|
|
|
|
//合并连续的枚举值
|
|
|
private fun mergeContinuousEnum(input: List<String>): List<String> {
|
|
|
if (input.isEmpty()) return emptyList()
|
|
|
|
|
|
val result = mutableListOf<String>()
|
|
|
val enumValues = if (input.firstOrNull() in monthList) monthList else weekList
|
|
|
|
|
|
var start = enumValues.indexOf(input[0])
|
|
|
var end = enumValues.indexOf(input[0])
|
|
|
|
|
|
for (i in 1 until input.size) {
|
|
|
val currentIndex = enumValues.indexOf(input[i])
|
|
|
if (currentIndex == end + 1) {
|
|
|
end = currentIndex
|
|
|
} else {
|
|
|
if (start == end) {
|
|
|
result.add(enumValues[start])
|
|
|
} else {
|
|
|
result.add("${enumValues[start]}-${enumValues[end]}")
|
|
|
}
|
|
|
start = currentIndex
|
|
|
end = currentIndex
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (start == end) {
|
|
|
result.add(enumValues[start])
|
|
|
} else {
|
|
|
result.add("${enumValues[start]}-${enumValues[end]}")
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
//合并连续的数字
|
|
|
private fun mergeContinuousItems(input: List<String>, stringFormat: String = "%d"): List<String> {
|
|
|
if (input.isEmpty()) return emptyList()
|
|
|
|
|
|
val items = input.map { it.toInt() }.sorted()
|
|
|
|
|
|
val result = mutableListOf<String>()
|
|
|
var start = items[0]
|
|
|
var end = items[0]
|
|
|
|
|
|
for (i in 1 until items.size) {
|
|
|
if (items[i] == end + 1) {
|
|
|
end = items[i]
|
|
|
} else {
|
|
|
if (start == end) {
|
|
|
result.add(String.format(stringFormat, start))
|
|
|
} else {
|
|
|
result.add(String.format(stringFormat, start) + "-" + String.format(stringFormat, end))
|
|
|
}
|
|
|
start = items[i]
|
|
|
end = items[i]
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (start == end) {
|
|
|
result.add(String.format(stringFormat, start))
|
|
|
} else {
|
|
|
result.add(String.format(stringFormat, start) + "-" + String.format(stringFormat, end))
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
//还原被合并的连续数字
|
|
|
private fun restoreMergedItems(mergedString: String, stringFormat: String = "%d"): List<String> {
|
|
|
if (mergedString.isEmpty()) return emptyList()
|
|
|
|
|
|
val items = mutableListOf<String>()
|
|
|
val ranges = mergedString.split(",")
|
|
|
|
|
|
for (range in ranges) {
|
|
|
val rangeParts = range.split("-")
|
|
|
if (rangeParts.size == 1) {
|
|
|
items.add(rangeParts[0])
|
|
|
} else if (rangeParts.size == 2) {
|
|
|
val start = rangeParts[0].toInt()
|
|
|
val end = rangeParts[1].toInt()
|
|
|
for (i in start..end) {
|
|
|
items.add(String.format(stringFormat, i))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return items
|
|
|
}
|
|
|
|
|
|
//检查设置
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
private fun checkSetting(): CronSetting {
|
|
|
second = binding!!.etSecond.text.toString().trim()
|
|
|
minute = binding!!.etMinute.text.toString().trim()
|
|
|
hour = binding!!.etHour.text.toString().trim()
|
|
|
day = binding!!.etDay.text.toString().trim()
|
|
|
month = binding!!.etMonth.text.toString().trim()
|
|
|
week = binding!!.etWeek.text.toString().trim()
|
|
|
year = binding!!.etYear.text.toString().trim()
|
|
|
|
|
|
expression = "$second $minute $hour $day $month $week $year"
|
|
|
description = ""
|
|
|
Log.d(TAG, "checkSetting, expression:$expression")
|
|
|
|
|
|
//判断cronExpression是否有效
|
|
|
CronExpression.validateExpression(expression)
|
|
|
|
|
|
//生成cron表达式描述
|
|
|
val options = Options()
|
|
|
options.isTwentyFourHourTime = true
|
|
|
//TODO:支持多语言
|
|
|
val locale = Locale.getDefault()
|
|
|
//Chinese, Japanese, Korean and other East Asian languages have no spaces between words
|
|
|
options.isNeedSpaceBetweenWords = locale == Locale("zh") || locale == Locale("ja") || locale == Locale("ko")
|
|
|
description = CronExpressionDescriptor.getDescription(expression, options, locale)
|
|
|
|
|
|
return CronSetting(description, expression)
|
|
|
}
|
|
|
} |