vue+elementUI实现动态时间段的禁用disabledDate

动态时间段的禁用disabledDate

不知道大家遇到过这样的需求没? 每一行的开始日期和结束日期区间不能重叠,但是可以出现中断.如: 第一行开始时间-结束时间:2020.1-2020.3,下一行数据不能在1月到3月,可以为2020.5-2020.7.结束日期默认为至今(本来可以使用 daterange 的,就是因为这句话,避免不了了).点击添加按钮,可以在表格下方新增一行,操作同上.
本来自己想着还挺简单的,可是随着行数添加的越多,发现越复杂,没办法 需求已经确定了改是改不了了,硬刚吧!

实现的效果

点击添加一行,上面两行的已经选过的不能再选(图1),但是你点击已经选过的本行的是可以修改的(图2)
在这里插入图片描述
在这里插入图片描述
里面其实有好多小的细节,里面都有所处理的,直接上代码了,完整的

<template>
  <div class="dateRange">
    <div style="margin:20px 0;">
      <el-button type="primary" @click="add">添加</el-button>
    </div>
    <el-table
      :data="tableData"
      style="width: 100%"
    >
      <el-table-column
        prop="end_date"
        label="模型选择"
      >
        <template slot-scope="scope">
          <el-select v-model="scope.row.model_select" placeholder="请选择" style="width:100%;">
            <el-option
              v-for="item in modelList"
              :key="item.indexId"
              :label="item.indexName"
              :value="item.indexId"
            />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column
        prop="start_date"
        label="开始日期"
        type="date"
      >
        <template slot-scope="scope">
          <el-date-picker
            v-model="scope.row.start_date"
            type="date"
            value-format="yyyy-MM-dd"
            :picker-options="pickerStartOptions"
            @focus="(...arg)=>changeStartDate(...arg,scope.$index,scope.row)"
          />
        </template>
      </el-table-column>
      <el-table-column
        prop="end_date"
        label="结束日期"
        type="date"
      >
        <template slot-scope="scope">
          <el-date-picker
            v-model="scope.row.end_date"
            type="date"
            value-format="yyyy-MM-dd"
            :picker-options="pickerEndOptions"
            @focus="(...arg)=>changeEndDate(...arg,scope.$index,scope.row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="100">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="danger"
            @click="handleDelete(scope.$index, scope.row)"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
import dayjs from 'dayjs'
export default {
  name: 'Test',
  props: {
    // table 数据
    dateRangeList: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 模型选择的下拉框
    modelList: {
      type: Array,
      default: () => {
        return [{
          indexId: '0',
          indexName: '红烧肉'
        }, {
          indexId: '1',
          indexName: '黄金糕'
        }]
      }
    }
  },
  data() {
    return {
      tableData: [{ start_date: '2020-12-07',
        end_date: '2020-12-18',
        model_select: '0' },
      { start_date: '2020-11-08',
        end_date: '2020-11-18',
        model_select: '1' }
      ],
      row: null,
      rowIndex: null,
      // 开始时间
      pickerStartOptions: {
        disabledDate: (time) => {
          const obj = {}
          for (let i = 0; i < this.tableData.length; i++) {
            if (i !== this.rowIndex) {
              // 第一次循环后 为了避免覆盖掉 用obj[time] ||
              obj[time] = obj[time] || +dayjs(time).format('YYYYMMDD') >= +dayjs(this.tableData[i].start_date).format('YYYYMMDD') && +dayjs(time).format('YYYYMMDD') <= +dayjs(this.tableData[i].end_date).format('YYYYMMDD')
            }
          }
          return obj[time]
        }
      },
      // 结束时间
      pickerEndOptions: {
        disabledDate: (time) => {
          const obj = {}
          for (let i = 0; i < this.tableData.length; i++) {
            if (i !== this.rowIndex) {
              obj[time] = obj[time] || +dayjs(time).format('YYYYMMDD') >= +dayjs(this.tableData[i].start_date).format('YYYYMMDD') && +dayjs(time).format('YYYYMMDD') <= +dayjs(this.tableData[i].end_date).format('YYYYMMDD')
            }
          }
          return obj[time]
        }
      }
    }
  },
  watch: {
    tableData: {
      deep: true,
      handler(val) {
        console.log('本来想监听排序一下', val)
      }
    }
  },
  created() {
    this.initList()
  },
  methods: {
    // 初始化表格数据,回显已经保存的数据
    initList() {
      this.dateRangeList.forEach(item => {
        this.tableData.push(item)
      })
    },
    // 数组按照时间排序函数
    arrSort(val) {
      return val.sort(function(a, b) {
        return +dayjs(a.start_date).format('YYYYMMDD') - +dayjs(b.start_date).format('YYYYMMDD')
      })
    },
    // 添加按钮
    add() {
      const obj = {
        start_date: '',
        end_date: '',
        model_select: ''
      }
      this.row = this.tableData[this.tableData.length]
      this.rowIndex = this.tableData.length
      this.tableData.push(obj)
      this.arrSort(this.tableData)
    },
    // 选择/获取焦点开始时间
    changeStartDate(val, idx, row) {
      this.row = row
      this.rowIndex = idx
      this.changeDate(val, idx, row)
    },
    // 选择获取焦点结束时间
    changeEndDate(val, idx, row) {
      this.row = row
      this.rowIndex = idx
      this.changeDate(val, idx, row)
    },
    // 时间重叠判断方法
    changeDate(val, idx, row) {
      this.tableData.find((item, index) => {
        if ((index !== idx) && row.start_date && row.end_date) {
          // 之前选择的时间区间只要在新选择的时间区间内,属于重叠
          const judge01 = +dayjs(row.start_date).format('YYYYMMDD') <= +dayjs(item.start_date).format('YYYYMMDD') && +dayjs(item.start_date).format('YYYYMMDD') <= +dayjs(row.end_date).format('YYYYMMDD')
          const judge02 = +dayjs(row.start_date).format('YYYYMMDD') <= +dayjs(item.end_date).format('YYYYMMDD') && +dayjs(item.end_date).format('YYYYMMDD') <= +dayjs(row.end_date).format('YYYYMMDD')
          if (judge01 && judge02) {
            this.$message({
              type: 'error',
              message: '时间区间重叠,请重新选择'
            })
            this.tableData[idx].start_date = ''
            this.tableData[idx].end_date = ''
          }
        }
      })
      // 两个都选择好了 排下序
      if (row.start_date && row.end_date) {
        this.arrSort(this.tableData)
      }
    },
    //  删除 按钮
    handleDelete(index, row) {
      this.tableData.splice(index, 1)
    }
  }

}
</script>

<style lang="scss">
.dateRange{
  .el-table td {
    padding:2px 0;
  }
}
</style>

这只是本人做的一个小demo,自己测的没啥问题,如果你需要就拿走,如果有什么问题,欢迎提出大家一块更正

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Spring Boot 和 Vue 结合使用,可以通过 Element UI 来实现动态路由。 具体步骤如下: 1. 在 Spring Boot 中,定义一个 API 接口,用于返回动态路由的配置信息,例如菜单列表、权限信息等。 2. 在 Vue 中,使用 axios 等工具调用该 API 接口获取动态路由的配置信息。 3. 在 Vue 中,使用 vue-router 来实现路由功能。在路由配置中,使用获取到的动态路由信息来动态生成路由。例如,使用菜单列表来生成菜单路由,使用权限信息来控制路由的访问权限等。 4. 在 Vue 中,结合 Element UI 的组件,可以实现一些常见的路由功能,例如面包屑导航、菜单栏等。 综上所述,通过 Spring Boot、VueElement UI 的结合,可以实现动态路由功能,从而实现更加灵活、可扩展的前端页面管理。 ### 回答2: Spring Boot是一个开发框架,Vue是一个前端框架,Element UI是一个UI组件库,如何实现动态路由呢? 首先,在Spring Boot后端,需要定义一个接口来获取动态路由的数据。可以使用一个数据库表来存储路由信息,如路由路径、组件名称、图标等。然后,通过编写一个控制器类,来处理获取动态路由数据的请求。在该控制器类中,可以调用相应的服务类或数据访问层来获取路由数据,并返回给前端。 接下来,在Vue前端项目中,可以使用Vue Router来实现动态路由。可以在项目的入口文件(如main.js)中,通过发送请求获取动态路由数据。可以使用axios等库来发送请求,获取后端返回的动态路由数据。获取到数据后,可以通过遍历的方式,动态地把路由配置项添加到Vue Router中。 同时,在项目中引入Element UI组件库,可以使用其中的菜单、导航等组件,来展示动态路由。可以根据获取的动态路由数据,来生成菜单和导航栏的数据,并将其展示在页面中。 为了实现动态路由的跳转,可以使用Vue Router中的路由守卫(如beforeEach),在路由跳转之前判断是否有权限访问该路由。可以根据当前用户的权限信息,来判断是否有权限访问该路由。如果没有权限,则可以跳转到其他页面或者显示相应的提示信息。 总结来说,通过在Spring Boot后端定义接口获取动态路由数据,并在Vue前端项目中将其配置到Vue Router中,配合使用Element UI的菜单、导航组件,就可以实现Spring Boot、VueElement UI的动态路由。 ### 回答3: 要实现动态路由,我们可以结合使用Spring Boot、VueElement UI。 首先,在Spring Boot后端,我们需要建立一个API接口,用于获取动态路由的数据。这个接口可以返回一个JSON对象,包含了多个路由对象的信息,如路由名称、路径、组件等。 接下来,在Vue前端,我们可以使用Element UI的导航菜单组件来实现动态路由。首先,我们需要在Vue项目中安装Element UI,并引入导航菜单组件。然后,在主页面组件中,我们可以通过调用后端的API接口获取动态路由数据,然后根据返回的数据动态生成导航菜单。可以使用Vue Router来管理路由,并使用 `<router-view>` 标签来展示对应的页面组件。 在生成导航菜单时,我们可以使用递归组件来实现无限嵌套的导航菜单结构。每个导航菜单项可以绑定点击事件,当用户点击菜单项时,可以通过Vue Router进行路由跳转,展示对应的页面组件。 为了保证路由权限控制,我们可以在后端API接口中加入用户权限验证的逻辑。在前端,我们可以根据用户的角色或权限信息动态生成导航菜单,只展示用户有权限访问的路由。 总结来说,使用Spring Boot提供API接口获取动态路由数据,然后在Vue前端使用Element UI的导航菜单组件构建动态路由。通过递归组件生成无限嵌套的导航菜单,并通过Vue Router实现路由跳转。同时,可以结合用户权限信息进行路由权限控制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值