我正在尝试解决Vue JS应用程序表单的付款频率<select>
的问题。为了对我所拥有的内容进行一些解释,我将在此处添加一些上下文。
有一个申请表,带有一个<select>
框,其中有一些选项供用户选择下一次付款的时间,例如:该月的最后一个工作日,每周,每两周,最后一个星期一一个月,该月的最后一个星期二等,我将在下面列出可用的选项。
用户选择合适的<option>
,并自动计算其下一个和下一个支付日期,例如:下一个支付:30/08/2019,后续支付:27/09/2019。用户可以根据需要选择编辑这些字段。
下一个支付日期有3个输入字段,以下支付日期有(DD / MM / YYYY)字段3个输入字段。
我遇到的问题与每月最后周的支付频率选项有关,例如:该月的最后一个星期一,该月的最后一个星期二到星期五。问题是,例如,如果我在每月的最后一个星期四,假设日期是29/08/2019,然后选择选项该月的最后一个星期一,而不是自动将1个月添加到月份字段中,它将保留在当前月份,这是不正确的,因为您不能有过去的下一个支付日期。
我使用的是 Moment JS (2.24.0版),并且使用的是 Vue JS (2.6.10版),还有软件包 vee-validate 用于已经设置的验证。
我有一些方法可以用来确定用户的下一个和之后的支付日期,下面列出的payFrequencyChange
方法计算出用户可以选择的每个可用支付频率选项。我试过检查代码,似乎应该根据日期正确地计算 month 字段,但不是。
这是有问题的代码:
new Vue({
el: '#application-form',
data: {
frequency: [{ value: 0, name: 'Last working day of month' }, { value: 1, name: 'Weekly' }, { value: 2, name: 'Four weekly' }, { value: 10, name: 'Specific Date' }, { value: 3, name: 'Bi-Weekly' }, { value: 9, name: 'Last Friday of month' }, { value: 5, name: 'Last Monday of month' }, { value: 6, name: 'Last Tuesday of month' }, { value: 7, name: 'Last Wednesday of month' }, { value: 8, name: 'Last Thursday of month' }],
NextPaydateError: false,
FollowingPaydateError: false,
formData: {
EmpPayFrequency: '',
NextPaydate: '',
FollowingPaydate: '',
NextPaydateDay: '',
NextPaydateMonth: '',
NextPaydateYear: '',
FollowingPaydateDay: '',
FollowingPaydateMonth: '',
FollowingPaydateYear: ''
}
},
methods: {
/**
* Switch fields
*/
switchToField(fieldSwitchName, fieldValue, fieldLength) {
if (String(fieldValue).length >= fieldLength) {
this.$refs[fieldSwitchName].focus();
}
},
/**
* Leading Zero
* @param {int} input
* @param {bool} years
*/
leadingZeros: function leadingZeros(input, years = false) {
if (!years) {
if (String(input).length === 1) return '0' + input
} else {
if (String(input).length === 2) {
if (parseInt(input) > 50 && parseInt(input) < 100) {
return '19' + input
}
}
}
return input
},
/**
* Next Pay Date Change
*/
nextPayDateChange: function nextPayDateChange() {
string = this.formData.NextPaydateYear + '-' + this.formData.NextPaydateMonth + '-' + this.formData.NextPaydateDay
date = moment(string).format('DD/MM/YYYY')
if (this.formData.NextPaydateYear === '') return
this.NextPaydateError = (date === 'Invalid date') ? true : false
this.formData.NextPaydate = date
},
/**
* Following Pay Date Change
*/
followingPayDateChange: function followingPayDateChange() {
nextDate = this.formData.NextPaydateYear + '-' + this.formData.NextPaydateMonth + '-' + this.formData.NextPaydateDay
followingDate = this.formData.FollowingPaydateYear + '-' + this.formData.FollowingPaydateMonth + '-' + this.formData.FollowingPaydateDay
if (!moment(followingDate).isAfter(moment(nextDate))) {
this.FollowingPaydateError = true
return
}
date = moment(followingDate).format('DD/MM/YYYY')
if (this.formData.FollowingPaydateYear === '') return
this.FollowingPaydateError = (date === 'Invalid date') ? true : false
this.formData.FollowingPaydate = date
},
/**
* Find Last Working Day
* @param {bool} nextMonth
*/
lastBusinessDay: function lastBusinessDay(nextMonth) {
dateOffset = {
'Saturday': 1,
'Sunday': 2
}
currentDate = new Date()
date = new Date(currentDate.getFullYear(), currentDate.getMonth() + (nextMonth ? 2 : 1), 0)
lastDay = date.toLocaleString('en-GB', {
day: 'numeric'
})
lastWeekday = date.toLocaleString('en-GB', {
weekday: 'long',
})
return dateOffset[lastWeekday] ? lastDay - dateOffset[lastWeekday] : lastDay
},
/**
* Find Last Weekday
* @param {object} monthMoment
* @param {int} dayInt
*/
lastWeekdayOfMonth: function weekly(monthMoment, dayInt) {
var lastDay = monthMoment.endOf('month').startOf('day')
for (let i = 0; i <= 10; i++) {
if (lastDay.day() === dayInt) {
return lastDay
} else {
lastDay.subtract(1, 'days')
}
}
},
/**
* Weekly Workouts
*/
weekly: function weekly(year, month, date, day) {
date = new Date()
offset = 4
result = null
if ('undefined' === typeof day || null === day) {
day = 5
}
if ('undefined' === typeof year || null === year) {
year = date.getFullYear()
}
if ('undefined' === typeof month || null === month) {
month = date.getMonth()
}
do {
result = new Date(year, month, date.getDate() + offset)
offset++
} while (result.getDay() !== day)
return result
},
/**
* Pay Frequency Change
* @param {int} value
*/
payFrequencyChange: function payFrequencyChange(value) {
var elems = document.querySelectorAll('.dobbox.is-invalid')
if (typeof elems === 'object') {
elems.forEach.call(elems, function(el) {
el.classList.remove('is-invalid')
});
}
currentDate = new Date()
switch (parseInt(value)) {
case 0: // last working day
next = {
day: this.lastBusinessDay(false),
month: currentDate.getMonth() + 1,
year: currentDate.getFullYear()
}
following = {
day: this.lastBusinessDay(true),
month: ((currentDate.getMonth() + 2) === 13) ? 1 : currentDate.getMonth() + 2,
year: ((currentDate.getMonth() + 2) === 13) ? currentDate.getFullYear() + 1 : currentDate.getFullYear()
}
break
case 1: // weekly
next = this.weekly(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 5)
follow = new Date(this.weekly(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 5))
following = follow.setDate(follow.getDate() + 7)
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
case 2: // four weekly
next = this.weekly(currentDate.getFullYear(),currentDate.getMonth(), currentDate.getDate() + 4)
d = new Date(this.weekly(currentDate.getFullYear(),currentDate.getMonth(), currentDate.getDate() + 4))
d.setDate(d.getDate() + 28)
following = d
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
case 10: // specific date
next = { day: '', month: '', year: '' }
following = { day: '', month: '', year: '' }
break
case 3: // bi-weekly
next = { day: '', month: '', year: '' }
following = { day: '', month: '', year: '' }
break
case 9: // last friday
next = this.lastWeekdayOfMonth(moment(), 5)
following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 5)
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
case 8: // last thursday
next = this.lastWeekdayOfMonth(moment(), 4)
following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 4)
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
case 7: // last wednesday
next = this.lastWeekdayOfMonth(moment(), 3)
following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 3)
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
case 6: // last tuesday
next = this.lastWeekdayOfMonth(moment(), 2)
following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 2)
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
case 5: // last monday
next = this.lastWeekdayOfMonth(moment(), 1)
following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 1)
next = {
day: moment(next).format('DD'),
month: moment(next).format('MM'),
year: moment(next).format('YYYY')
}
following = {
day: moment(following).format('DD'),
month: moment(following).format('MM'),
year: moment(following).format('YYYY')
}
break
}
// Populate new dates
this.formData.NextPaydateDay = this.leadingZeros(next.day)
this.formData.NextPaydateYear = next.year
this.formData.NextPaydateMonth = this.leadingZeros(next.month)
this.formData.FollowingPaydateDay = this.leadingZeros(following.day)
this.formData.FollowingPaydateYear = following.year
this.formData.FollowingPaydateMonth = this.leadingZeros(following.month)
setTimeout(function () { // Prevent validation errors
this.NextPaydateError = this.FollowingPaydateError = false
}.bind(this), 10)
}
},
watch: {
'formData.NextPaydateYear': function formDataNextPaydateYear() {
this.nextPayDateChange()
},
'formData.FollowingPaydateYear': function formDataFollowingPaydateYear() {
this.followingPayDateChange()
}
}
})
因此,如上所述,一切都将在月初顺利进行,但是,如果您将计算机的时间/日期更新为例如2019年8月29日,则在选择以下选项时:上周一至周四,则应增加“下个月”和“下个月”字段,但在选择“最后一个星期五”时,它应保留在当月,除非在月末前三天,然后也应增加。
我知道要花很多钱,因此还准备了一支密码笔:
https://codepen.io/sts-ryan-holton/pen/rXGzox
这里会提供一些帮助,这不是我写的,所以不是完全100%确定如何修复/添加这一关键功能。
答案 0 :(得分:0)
您可以通过在 lastWeekdayOfMonth 函数中更改以下几项来获得所需的功能
lastWeekdayOfMonth: function weekly(monthMoment, dayInt) {
var lastDay = moment(monthMoment).endOf('month').startOf('day')
var result = this.__lastWeekdayOfMonth(lastDay, dayInt)
if( result.isBefore(monthMoment) ) {
lastDay = moment(lastDay).add(1, 'month')
result = this.__lastWeekdayOfMonth(lastDay, dayInt)
}
return result
},
__lastWeekdayOfMonth: function __weekly(lastDay, dayInt) {
for (let i = 0; i <= 10; i++) {
if (lastDay.day() === dayInt) {
return lastDay
} else {
lastDay.subtract(1, 'days')
}
}
},
在这里,我对代码进行了一些模块化,并添加了另一个可以完成特定工作的功能。
我只是检查结果是否在给定日期之前,然后检查下个月。