Vue前端对请假模块——请假开始时间和请假结束时间的校验处理

开发背景:Vue+element组件开发

业务需求:用户提交请假申请单,请假申请的业务逻辑处理

实现:用户选择开始时间需要大于本地时间,不得大于请假结束时间,请假时长根据每日工作时间实现累加计算

页面布局

在前端页面选择的是el-date-picker组件

 <!-- 请假开始时间表单项 -->
<el-form-item
  prop="start_time" <!-- 绑定表单验证规则的属性名 -->
  label="请假开始时间" <!-- 表单项标签文本 -->
  style="height: 55px" <!-- 设置表单项高度 -->
  label-width="120px" <!-- 设置标签宽度 -->
  :required="true" <!-- 标记为必填项 -->
>
  <el-col :span="11"> <!-- 使用 Element UI 的 Col 布局,设置列宽 -->
    <el-date-picker <!-- 日期时间选择器组件 -->
      type="datetime" <!-- 设置类型为日期和时间选择 -->
      placeholder="选择日期" <!-- 提示信息 -->
      v-model="form.start_time" <!-- 绑定到表单对象的 start_time 属性 -->
      style="width: 100%" <!-- 设置组件宽度为100% -->
      value-format="yyyy-MM-dd HH:mm:ss" <!-- 设置选中值的时间格式 -->
      :picker-options="pickerOptionsStart" <!-- 传入开始时间的选择器选项 -->
      @change="calculateLeaveHours" <!-- 当选择日期发生改变时触发的方法 -->
    ></el-date-picker>
  </el-col>
</el-form-item>

<!-- 请假结束时间表单项 -->
<el-form-item
  label="请假结束时间"
  style="height: 55px"
  prop="end_time"
  label-width="120px"
  :required="true"
>
  <el-col :span="11">
    <el-date-picker
      type="datetime"
      placeholder="选择日期"
      v-model="form.end_time" <!-- 绑定到表单对象的 end_time 属性 -->
      style="width: 100%"
      value-format="yyyy-MM-dd HH:mm:ss"
      :picker-options="pickerOptionsEnd" <!-- 传入结束时间的选择器选项 -->
      @change="calculateLeaveHours" <!-- 同样在结束时间改变时触发计算方法 -->
    ></el-date-picker>
  </el-col>
</el-form-item>

<!-- 请假时长(小时)展示表单项 -->
<el-form-item label="请假时长(小时)" prop="hours" label-width="120px">
  <el-input <!-- 输入框组件 -->
    v-model="form.hours" <!-- 绑定到表单对象的 hours 属性 -->
    disabled <!-- 设置输入框为禁用状态,仅用于显示计算出的请假时长 -->
  ></el-input>
</el-form-item>

用户选择开始时间的范围校验

校验是通过:picker-options  时间中的变化是@change

 :picker-options="pickerOptionsStart"
          @change="calculateLeaveHours"

通过picker-options  vue动态绑定属性设定了选择器的自定义配置,例如开始时间需大于本地时间且需要小于结束时间

开始时间选择代码如下:

// pickerOptionsStart 定义开始时间选择器的自定义选项
pickerOptionsStart: {
  // disabledDate 是一个函数,用于决定日期选择器中哪些日期应被禁用(即不可选)
  disabledDate: (time) => {
    // 获取表单中结束时间的值
    let endDateVal = this.form.end_time;
    
    // 创建一个新的 Date 对象表示当前本地时间,并将其时间部分设置为0,确保包含今天整天的时间范围
    let now = new Date();
    now.setHours(0, 0, 0, 0);

    // 如果结束时间未设置,则只允许用户选择从当前时间(包含今天)到未来的所有时间
    if (!endDateVal) {
      return time.getTime() < now.getTime(); 
    }

    // 同时满足以下条件时,该日期将被禁用:
    // 1. 开始时间需大于等于当前本地时间
    // 2. 开始时间需小于结束时间
    return (
      // 时间戳比较:如果开始时间早于当前时间 或者 开始时间晚于已设置的结束时间,则禁用该日期
      time.getTime() < now.getTime() ||
      time.getTime() > new Date(endDateVal).getTime()
    );
  },
},

获取结束时间的值,如果有则从本地时间到结束时间,如果没有就从本地时间到未来的时间,创建Date对象来获取当前本地的时间,至于为什么需要包含今天整体的时间是因为如果只判断开始时间大于本地时间的话,在时间选择器里今天的日期也是被禁止掉了的,这对于用户的体验是不好的,同理,结束时间与开始时间类似,但是这个方法的缺陷便是用户可以在下午选择今天早上的时间,这对于业务是不满足的,后面会有解决方案

结束时间范围选择

如果用户先选择结束时间时,如:2-29,开始时间就只能从26-29进行选择

代码如下:

// pickerOptionsEnd 定义结束时间选择器的自定义选项
      pickerOptionsEnd: {
        // disabledDate 是一个函数,用于决定日期选择器中哪些日期应被禁用(即不可选)
        disabledDate: (time) => {
          // 获取表单中开始时间的值
          let beginDateVal = this.form.start_time;

          // 创建一个新的 Date 对象表示当前本地时间
          const currentDate = new Date();

          // 确保结束时间大于开始时间(如果开始时间已设置)
          if (beginDateVal) {
            return time.getTime() <= new Date(beginDateVal).getTime();
          }

          // 同时允许用户选择今天的日期作为结束时间,因此仅当结束时间早于当前时间才禁用
          return time.getTime() < currentDate.setHours(0, 0, 0, 0);
        },
      },

对于开始时间的校验以及计算请假时长

为了解决用户在当天可以选择任意的时间段以及计算请假时长,在开始时间和结束时间发生变化时便执行方法

methods: {
    //计算请假时长
    calculateLeaveHours() {}
    
}

当用户选择的开始时间小于本地时间的5分钟之前时(因为涉及到秒数,选择的开始时间会一直小于本地时间,为用户操作保留缓冲区间),提示用户并重置开始时间为本地时间,当结束时间小于本地时间时,则重置结束时间为选择的开始时间后一个小时

 const startTime = new Date(this.form.start_time);
      const endTime = new Date(this.form.end_time);

      let now = new Date();

      const fiveMinutesAgo = new Date();
      fiveMinutesAgo.setMinutes(now.getMinutes() - 5);
      fiveMinutesAgo.setSeconds(0);
      fiveMinutesAgo.setMilliseconds(0);

      if (startTime < fiveMinutesAgo) {
        this.$message({
          message: "开始时间需在当前时间附近,已为您选择当前时间!",
          type: "warning",
        });
        this.form.start_time = new Date();
      }

      if (endTime < startTime) {
        this.$message({
          message:
            "结束时间小于开始时间,已为您选择结束时间为开始时间后一个小时!",
          type: "warning",
        });
        this.form.end_time = new Date(startTime.getTime() + 60 * 60 * 1000);
      }

请假时长的计算

// 初始化请假时长
      let leaveHours = 0;

      // 计算每天的工作时间
      let currentDate = new Date(startTime);
      while (currentDate < endTime) {
        const currentHour = currentDate.getHours(); // 获取当前小时数
        const currentMinute = currentDate.getMinutes(); // 获取当前分钟数

        // 判断当前时间是否在工作时间段内,若在则加入工作时间
        if (
          // 上午工作时间段:8:30 - 11:20
          (((currentHour === 8 && currentMinute >= 30) || currentHour > 8) &&
            ((currentHour === 11 && currentMinute < 20) || currentHour < 11)) ||
          // 下午工作时间段:14:00 - 18:00
          ((currentHour === 14 || currentHour === 18) && currentMinute >= 0) ||
          (currentHour > 14 && currentHour < 18) ||
          // 晚上工作时间段:19:00 - 20:30
          (((currentHour === 19 && currentMinute >= 0) || currentHour > 19) &&
            ((currentHour === 20 && currentMinute <= 30) || currentHour < 20))
        ) {
          // 在工作时间段内,加入工作时间
          leaveHours += 0.1;
        }

        // 将日期增加一小时
        currentDate.setMinutes(currentMinute + 6); // 以6分钟为间隔加入工作时间
      }

      // 更新请假时长
      this.form.hours = leaveHours.toFixed(1);

这样的基本模块便完善得七七八八了,但在其中依然还是有些小问题,例如如果用户先选择时间结束后,再重置便会导致请假时长会一直计算的问题

最初想的解决方案是如果开始时间为空的话,就重置时间跳出方法,

// 首先检查开始时间和结束时间是否为空,如果任一为空则跳出此方法
      if (!this.form.start_time || !this.form.end_time) {
        return this.form.hours=0;
      }

但是如果用户选择的开始时间小于本地时间的话就不能再进行判断了,所以进行了优化

if (this.form.hours !=0 &&(!this.form.start_time || !this.form.end_time)) {
        return this.form.hours=0;
      }

在周末的情况下我们也不应该把周末的时间计算到工作日中,代码优化如下:

const weekends = [0, 6];  
if (weekends.includes(currentDay)) {
          currentDate.setDate(currentDate.getDate() + 1); // 跳到下一天
          currentDate.setHours(8); // 设置小时为早上8点
          currentDate.setMinutes(0); // 设置分钟为0分
          continue; // 跳过后面的代码,继续下一轮循环
        }

设置了一个数组只要是周末周六就直接跳到下一天

这样便都解决了

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,根据你的需求,我们可以稍作修改来实现根据开始时间结束时间计算请假天数,如果开始时间结束时间只相差半天,则请假天数为0.5天。以下是修改后的示例代码: ```html <template> <div> <label for="start-date">开始日期:</label> <input type="date" id="start-date" v-model="startDate"> <label for="start-time">开始时间:</label> <input type="time" id="start-time" v-model="startTime"> <label for="end-date">结束日期:</label> <input type="date" id="end-date" v-model="endDate"> <label for="end-time">结束时间:</label> <input type="time" id="end-time" v-model="endTime"> <p>请假天数: {{ leaveDays }}</p> </div> </template> <script> export default { data() { return { startDate: '', startTime: '', endDate: '', endTime: '' }; }, computed: { leaveDays() { if (this.startDate && this.startTime && this.endDate && this.endTime) { const startDateTime = new Date(this.startDate + 'T' + this.startTime); const endDateTime = new Date(this.endDate + 'T' + this.endTime); const diff = endDateTime - startDateTime; const halfDayInMillis = 12 * 60 * 60 * 1000; if (diff <= halfDayInMillis) { return 0.5; } else { const days = Math.floor(diff / (24 * 60 * 60 * 1000)); return days; } } else { return 0; } } } }; </script> ``` 在这个示例中,我们添加了`startTime`和`endTime`来绑定开始时间结束时间的输入框。我们将开始日期和开始时间结束日期和结束时间合并成一个完整的日期时间,并将其转换为`Date`对象进行计算。如果开始时间结束时间只相差半天(12小时),则请假天数为0.5天,否则按照整天计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值