尖峰平谷1天内时间段选择实现简述(vue+element纯前端)

提示:这是能源系统中涉及电价收费的部分,我涉及的能源不太深入,所以只展示尖峰平谷时间段选择,不涉及金钱,有些时间段功能是自己臆测的(每天多次尖时段,时段之间不冲突),所以只简述实现方法、适用场景和部分方法、代码,具体代码由于还未深入了解能源行业,可能有问题,暂不全部展示。


前言

1、尖峰平谷为鼓励用户合理安排用电时间,提升用电资源利用效率,每天将24小时划分成高峰、平谷四个时段,为适合不同时段用电量和用电量计算,并按照规定在智能电表中设置时间段。

2、要解决时间选择问题中的小问题:

①各个月的尖峰平谷方案是不同的,所以必须选择月份(月份是多选的,一个方案适配多个月份,但是一个月份是否有多个尖峰平谷方案?不确定)

②尖峰平谷是一天内的,不能超出一天限制(没发现其他能源系统是48小时制的,大部分我看到的是24小时,不排除48小时跨天形式的,只是我没找到)

③一天内尖峰平谷可以多次出现(不确定,看到的大部分是单次,偶尔多次),多个尖(峰、平、谷)时段不能重复或可连接(重复或连接的话要求合并为一个?也许)

④尖峰平谷之间可以连接,但不可重复?(例:尖时段是01:00-02:00和03:00-04:00,峰是2:00-3:00,这样是可以的,这样是可以连接为连续的数)


一、样式选择

1、尖峰平谷方案选择了el-tabs,因为里面有个“ editable @edit="handleTabsEdit" ”这个,可以动态增删方案,每个新增方案名称为‘方案’+index+1,直观展示第n个方案(虽然数组是从0开始的,这个真的恶心,总是弄混,改了好久,暂不展示,基本上大家都会,甚至用card自定义更好,只占用竖向空间,不挤压横向,我这个tabs+滑块占用横向太多了,不好)

2、月份选择使用了12个多选框组实现月份选择el-checkbox-group,每个方案勾选的月份要进行校验。(一个方案可以被多个月份选择,不能一个月有多个方案!?可能,代码也不展示,毕竟就是个1-12的多选框组)

3、时间段选择了滑块,没有使用element自带的el-time-select+picker-options,原因是不太直观,滑块是图形可以轻松发现冲突位置,但是时间选择器是文字描述,不太好发现,但是缺点也有,就是太占地方,一个滑块48(或24,区别是颗粒度是小时还是半小时的)个位置太长了,部分文字描述只能隐藏,但是时间选择器没有这个问题,可以做的很小(展示代码)

4、缺点:

        ①占地方,导致时间节点是一段一段的描述,而不是连着的,比如下图是48节点半小时颗粒度的尖峰平谷选择器

        ②颗粒度不能太细太小,仅仅48节点就这样了,如果是以10分钟记的颗粒度,那长度和文字描述都爆炸了(我看别人的一般半小时,也就随大流了)

         ③这个方案名称暂时没搞成可修改的,毕竟能动的代码就尽量少动

二、实现步骤

1.时间选择(滑块)

        1.先想明白颗粒度大小,我先做的是24小时的,但是老大说现在一般是半小时的,看别人的程序是半小时的,所以改为48,24小时很好理解,0代表00:00,1代表01:00……,48小时就是偶数代表(偶数/2 + :00)的时间,奇数是代表(奇数/2取整 + :30)的时间,到时候校验就通过1,2,3,4……比较,而不是比01:00、02:00……

        2.一开始尖峰平谷都是只有一个的,因为一是偷懒,二是对能源认识不够,但是后来甲方爸爸说不行,都要多的,所以改为多段尖峰平谷(多段的尖、峰、平、谷不会收费不同吧,别给我来个第一段尖时段收1块,第二段尖时段就收1.5了,不然还得加id区分,没有这么Σ(☉▽☉"a的要求吧)

        3.尖时段内部要先校验,可能出现三种情况,分别是正常(单时间段+多段不重复无法连接时间段),有重合时间段(例:00:00-01:00和00:00-02:00就重合了,可以合并为一个00:00-02:00),可连接时间段(例:00:00-01:00和01:00-02:00可连接为一个00:00-02:00),其中正常不管,剩下两个统称为可合并

        4.组内验重的方法:

                ①因为尖峰平谷都可以多次选择,所以尖(峰、平、谷)内部的数据使用二维数组,例如尖数组:[[0,1],[2,3]……],这样四个类型合成一个大的obj对象就是这样的

form: {
        tip: [[0, 1]], // 尖
        peak: [[0, 0]], // 峰
        flat: [[0, 0]], // 平
        valley: [[0, 0]] // 谷
      },

                ②如何确认是否重合:因为滑块和选择器这种都是长度为2的数组,所以只有头和尾,我想到的笨办法是先把数组拓充,之后数组合并为一个大数组,如果有重复元素,就证明可合并(3的第二第三种情况),不然正常。其中拓充数组使用for循环,起始为开始数据,长度是(结束-开始+1),使用push存入暂存的新数组;合并数组使用的是flat()方法,将[[0,1],[2,3]……]的数组改为[0,1,2,3……]这样的;之后试用new Set()获取去重之后的数组比较长度,如果长度一样,代表没重复的,如果长度不同,代表有可合并的

      // 承接最后结果进行比较的两个数组
      let list = [] // flat处理后的数组
      let copyList = [] // set处理后的数组
      // 循环尖峰平谷对应数组的子数组数据
      // 这里的form参考上面的数据结构
      form[name].map((item, index) => {
        let arr = []
        // 数组拓充
        for(let i = item[0]; i <= item[1] ; i++){
            arr.push(i)
        }
        list.push(arr)
      })
      // 数组合并
      list = list.flat()
      // 数组去重
      copyList = [...new Set(list)]
      // 0是一样长,没重复的,其他的都是不对的
      return list.length-copyList.length

                ③起始数据+最后数据例子(以尖举例):

                正常:起始:[ [0,5],[7,9] ]

                           拓充:[ [0,1,2,3,4,5],[7,8,9] ]

                           合并:[0,1,2,3,4,5,7,8,9]

                           去重:[0,1,2,3,4,5,7,8,9]  (去重后长度不变,没有可合并的)

                可合并1(重合):

                           起始:[ [0,5],[4,6] ]

                           拓充:[ [0,1,2,3,4,5],[4,5,6] ]

                           合并:[ 0,1,2,3,4,5,4,5,6 ]

                           去重:[ 0,1,2,3,4,5,6 ]   (去重后长度改变)

                可合并2(连接):

                           起始:[ [0,5],[5,7] ]

                           拓充:[ [0,1,2,3,4,5],[5,6,7] ]

                           合并:[ 0,1,2,3,4,5,5,6,7 ]

                           去重:[ 0,1,2,3,4,5,6,7 ]   (去重后长度改变)

        5.尖峰平谷之间校验:

                组内完成后进行组与组之间校验,我也没有好办法,所以笨办法*2(要有好的其他方法一定要用,我这个太shabby了),首先先了解接下来的数据具有的属性:在一个线性的数据中(组内),每个正整数都有两个属性,head和end,其中head是指以它开头,end是以它结尾,如果这个数在数组中间,那么它存在的小数据段及以它开头,又以它结尾(例:[0,1,2,3,4,5]中,0的属性是{head:true,end:false},5是{head:false,end:true},其他的元素可以把数组拆为一个一个长度为2的小数组来看,1既是[0,1]这个小数组的尾,又是[1,2]这个小数组的头,所以属性为{head:true,end:true},以此类推);通过这样给数据加上属性来判断是否重合,如果有重合,那么        

                ①有两个完全相同的数据对象(例:尖:[0,4],峰:[2,5],这是重合的,重合数据为3,4,尖3为{head:true,end:true},峰3也为{head:true,end:true},证明重合,4呢,4的在下面

                ②同一个数,一个在数组内,一个在数组两边(例:尖[0,4],峰[3,5],重合数据为4,因为4被包在了第二个数组里面,尖4{head:false,end:true},峰4{head:true,end:true},可以推出:如果一个数的head、end属性都是true,那么下次它再出现,必定重复)

                ③所以先拓展数组并给数据加属性,拓展数据同上,加属性通过判断数据位置,在头赋{head:true,end:false},在尾{head:false,end:true},中间是{head:true,end:true}

// 数组有两个值进行判断,没有进行尖峰平谷选择不判断,arr是[0,1,2,3……]
        arr.forEach((item,index)=>{
          if(index == 0){
            // 只有头属性
            obj[index] = {
              num:item,
              head: true,
              end: false
            }
          }else if(index == arr.length-1){
            // 只有尾属性
            obj[index] = {
              num:item,
              head: false,
              end: true
            }
          }else{
            // 头属性尾属性都有
            obj[index] = {
              num:item,
              head: true,
              end: true
            }
          }
        })

                ④各个组的数据处理完成后,将四个大组合并为一个超级大对象组,每个数据都有head、end属性,这时候new Set不太好用了,因为要比较的比较多,所以笨办法*3(我是把自己搞晕了,但所幸程序可以运行);先将数组内部不包括头尾的放在一个数组a1,再将只有数组头尾的放在另一个数组a2,先比较a1里有没有重复的元素(直接看看有没有重复的数,我这里懒得再搞了,直接将属性字符串化并拼接进行比较:''+item.num+item.head+item.end;比如a1有两个3,那么'3truetrue'一定等于'3truetrue',a2不行,毕竟a2要不是头要不是尾,'5truefalse'不等于'5falsetrue',除非a2有两个以上的5或其他元素,不过无所谓,a2内部不用比较,毕竟如果两个'5truefalse',那么在a1里一定有两个'6truetrue'),之后看a1和a2里有没有重复的数,有的话证明也重了,毕竟一个数在数组内部一定不能是另一个数组的头。这里先比较数组a1内部还是先比较a1和a2无所谓,都能校验

      let list = []
      // head是true,end是true,a1
      let arrcopy = []
      for(let i = 0;i<arr.length;i++){
        if(arr[i].head&&arr[i].end){
          arrcopy.push(arr[i])
        }
      }
      // head或end有一个是true,a2
      let arrcopy2 = []
      for(let i = 0;i<arr.length;i++){
        if((arr[i].head&&!arr[i].end)||(!arr[i].head&&arr[i].end)){
          arrcopy2.push(arr[i])
        }
      }
      // a1和a2比较有没有一样的数
      for(let i = 0;i<arrcopy.length;i++){
        for(let j = 0;j<arrcopy2.length;j++){
          if(arrcopy[i].num == arrcopy2[j].num){
            // 当全true的数组里和整集的有相同元素时
            return false
          }
        }
      }
      // 这里其实a1、a2分不分开无所谓,我没分开,原始超大数组直接比
      arr.map(item=>{
        list.push(''+item.num+item.head+item.end)
      })
      return list.length == [...new Set(list)].length

        这样尖峰平谷多选不冲突就实现了

2.源码

应该是免费的

尖峰平谷.vuehttps://download.csdn.net/download/qq_40950174/87409487


总结

1.有许多可以改进的地方,比如样式的自定义颜色,自定义的颗粒度、尖峰平谷大类的增删(现在只有尖峰平谷内部可以删改,大类只有尖峰平谷这四个)等

2.js方法太复杂,其实加了属性之后组内的也能进行校验,但因为先做的组内的,所以没办法了,又不想改,而且肯定有方法不加属性,比如某个元素在另一个数组的中间就证明重合了,但是我也懒得思考了,放弃了毁灭吧

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用 Element UI 中的 Input 组件和 Autocomplete 组件来实现搜索框功能。 首先,需要在页面中引入 Element UI 库和 Vue.js 库: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue + Element UI Search Box</title> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> </head> <body> <div id="app"> <el-autocomplete v-model="keyword" :fetch-suggestions="querySearchAsync" placeholder="请输入搜索关键字"> <el-button slot="append" icon="el-icon-search" @click="search">搜索</el-button> </el-autocomplete> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <script> new Vue({ el: '#app', data() { return { keyword: '', suggestions: [] }; }, methods: { querySearchAsync(queryString, cb) { // 在这里实现异步搜索逻辑,返回搜索结果数组 }, search() { // 在这里实现搜索操作 } } }); </script> </body> </html> ``` 然后,在 Vue 实例中定义一个 data 对象来保存搜索关键字和搜索结果,以及两个方法来实现搜索功能: - querySearchAsync:调用异步方法进行搜索,返回搜索结果数组给 Autocomplete 组件。 - search:根据搜索关键字进行具体的搜索操作。 接下来,需要在 querySearchAsync 方法中实现异步搜索逻辑,可以使用 Ajax 或者 Fetch API 发送异步请求获取搜索结果。搜索结果数组的格式需要符合 Autocomplete 组件的要求,即每个元素都是一个对象,包含 value 和 label 两个属性,分别表示搜索结果的值和显示文本。 ```javascript methods: { querySearchAsync(queryString, cb) { axios.get('/api/search', { params: { q: queryString } }).then(response => { const data = response.data; const suggestions = data.map(item => { return { value: item.id, label: item.name }; }); cb(suggestions); }).catch(error => { console.error(error); }); }, search() { // 根据 this.keyword 进行具体的搜索操作 } } ``` 以上代码使用 axios 库发送异步请求,返回的数据是一个包含多个对象的数组,每个对象包含 id 和 name 两个属性。在 querySearchAsync 方法中将数组转换成 Autocomplete 组件需要的格式,并调用 cb 方法将搜索结果返回给 Autocomplete 组件。 最后,在 search 方法中可以根据 this.keyword 属性进行具体的搜索操作,例如跳转到搜索结果页面、展示搜索结果列表等。 完成以上步骤后,就可以实现一个基于 Vue.jsElement UI 的前端搜索框。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值