vue3+ts 实现时间间隔选择器

  • 需求背景
  • 解决效果
  • 视频效果
  • balancedTimeElement.vue

需求背景

实现一个分片的时间间隔选择器,需要把显示时间段显示成图表,涉及一下集中数据转换

  • [“02:30-05:30”,“07:30-10:30”,“14:30-17:30”]
  • ‘[(2,5),(7,10),(14,17)]’
  • [4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 17, 18, 19, 20, 28, 29, 30, 31, 32, 33, 34]

解决效果

在这里插入图片描述

视频效果

时间间隔选择器

balancedTimeElement.vue

<!--/*** @author: liuk* @date: 2023/11/28* @describe: 时间间隔选择器* @CSDN:https://blog.csdn.net/hr_beginner?type=blog*/-->
<template><div><div class="hours-container"><div class="hours-item-header-box"><div class="hours-item-header" v-for="(_, i) in hours.slice(0,24)" :key="i">{{(i + 1 + '').padStart(2, 0)}}</div></div><div class="hours-item-box" ref="hoursItemRef"><template v-for="(_, i) in hours" :key="i"><div class="hours-item" :class="compClass(i)" @click="handleClick(i)" @mouseover="handleHover(i)"></div></template></div></div><div class="tips">提示: 向右选中,向左取消选择</div></div>
</template><script lang="ts" setup>
import {reactive, toRefs, ref, watch} from "vue";// Props
const props = defineProps(['manual_period'])// Emits
const emit = defineEmits(['data-passed'])// Ref
const hoursItemRef = ref(null)type numOrstr = number | string
type arrOrstr = any[] | stringinterface ModelType {hours: number[]selectStart: booleanstartIndex: numOrstrtimeRangeList: string[]timeRangeListIndex: numOrstr[]tempRangeIndex: number[]tips: arrOrstr
}const model: ModelType = reactive({hours: new Array(48).fill('').map((_, i) => i),selectStart: false,// 开始startIndex: '',// 开始下标timeRangeList: [],// 选择的时间段timeRangeListIndex: [],// 选中的下标tempRangeIndex: [],// 预选下标tips: '',})
const {hours,selectStart,startIndex,timeRangeList,timeRangeListIndex,tempRangeIndex,tips,
} = toRefs(model)watch(() => props.manual_period, (data) => {//'[(2,5),(7,10),(14,17)]'const str = data.replace(/\(|\)/g, (val) => { // '[[2,5],[7,10],[14,17]]'switch (val) {case "(":return "["case ")":return "]"}})model.timeRangeListIndex = JSON.parse(str).map(item => {const [x, y] = itemreturn new Array(2 * y - 2 * x + 1).fill(0).map((_, i) => i + 2 * x)}).flat()//  [4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 17, 18, 19, 20, 28, 29, 30, 31, 32, 33, 34]Array.from(hoursItemRef.value.children).forEach((dom: HTMLDivElement, index) => {if (model.timeRangeListIndex.includes(index)) {dom.className += ' selected'}})
})// 下标区间转换成时间区间
const transformedSection = () => {model.timeRangeList = [];let startTime = '', endTime = '', len = model.hours.length;for (let index = model.hours[0] * 2; index < 2 * (len + 1); index++) {if (model.timeRangeListIndex.indexOf(index) > -1) {if (startTime) {// 如果有开始时间,直接确定结束时间let endHour = Math.floor((index + 1) / 2);let endMin = (index + 1) % 2 === 0 ? "00" : "30";endTime = `${endHour < 10 ? '0' + endHour : endHour}:${endMin}`;} else {// 没有开始时间,确定当前点为开始时间let startHour = Math.floor(index / 2);let startMin = index % 2 === 0 ? "00" : "30";startTime = `${startHour < 10 ? '0' + startHour : startHour}:${startMin}`;}if (index === 2 * model.hours.length + 1) { // 如果是最后一格,直接结束endTime = `${Math.floor((index + 1) / 2)}:00`;model.timeRangeList.push(`${startTime ? startTime : "23:30"}-${endTime}`);startTime = '';endTime = '';}} else { // 若这个点不在选择区间,确定一个时间段if (startTime && endTime) {model.timeRangeList.push(`${startTime}-${endTime}`);startTime = '';endTime = '';} else if (startTime && !endTime) {// 这里可能只选半个小时let endHour = Math.floor(index / 2);let endMin = index % 2 === 0 ? "00" : "30";endTime = `${endHour < 10 ? '0' + endHour : endHour}:${endMin}`;model.timeRangeList.push(`${startTime}-${endTime}`);startTime = '';endTime = '';}}}model.tips = model.timeRangeList && model.timeRangeList.length > 0 ? model.timeRangeList : '';emit('data-passed', model.tips);
}// 点击事件
const handleClick = (index) => {if (model.selectStart) {if (index === model.startIndex) {// 双击取反if (model.timeRangeListIndex.indexOf(index) > -1) {model.timeRangeListIndex.splice(model.timeRangeListIndex.indexOf(index), 1);} else {model.timeRangeListIndex.push(model.startIndex);}} else if (index > model.startIndex) {// 选取数据--向右添加,向左取消while (index >= model.startIndex) {model.timeRangeListIndex.push(model.startIndex);model.startIndex = +model.startIndex + 1;}model.timeRangeListIndex = Array.from(new Set(model.timeRangeListIndex));} else {// 删除数据while (model.startIndex >= index) {if (model.timeRangeListIndex.indexOf(index) > -1) {model.timeRangeListIndex.splice(model.timeRangeListIndex.indexOf(index), 1);}index++;}}model.startIndex = '';transformedSection();model.tempRangeIndex = [];} else {model.startIndex = index;}model.selectStart = !model.selectStart;
}
// 预选区间
const handleHover = (index) => {if (model.selectStart) {model.tempRangeIndex = [];if (index > model.startIndex) {// 选取数据--向右添加,向左取消while (index >= model.startIndex) {model.tempRangeIndex.push(index);index--;}} else {// 删除数据while (model.startIndex >= index) {model.tempRangeIndex.push(index);index++;}}}
}
// 是否选中,计算className
const compClass = (index) => {if (index === model.startIndex) {return 'hours-item-left preSelected';}if (index >= model.startIndex) {if (model.tempRangeIndex.indexOf(index) > -1) {return 'hours-item-left preSelected';}} else {if (model.tempRangeIndex.indexOf(index) > -1) {return 'hours-item-left unSelected';}}return model.timeRangeListIndex.indexOf(index) > -1 ? 'hours-item-left selected' : 'hours-item-left';
}
</script><style lang="scss" scoped>
.hours-container {cursor: pointer;color: slategray;.hours-item-header-box {display: flex;width: 100%;height: 30px;.hours-item-header {width: 30px;height: 30px;text-align: center;box-sizing: border-box;line-height: 30px;border: 1px solid #5a5a5a;border-left: none;border-bottom: none;&:first-child {border-left: 1px solid #5a5a5a;}}}.hours-item-box {display: flex;width: 100%;.hours-item {width: 15px;height: 30px;border: 1px solid #474747;box-sizing: border-box;&.selected {background-color: #ffbf00 !important;border-bottom: 1px solid #c2d0f3;}&.preSelected {background-color: rgb(255, 191, 0);border-bottom: 1px solid #c2d0f3;}&.unSelected {background-color: #ffffff;border-bottom: 1px solid #c2d0f3;}}}
}.tips {width: 100%;line-height: 30px;margin-top: 10px;
}</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/185886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

掌握Python BentoML:构建、部署和管理机器学习模型

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com BentoML是一个开源的Python框架&#xff0c;旨在简化机器学习模型的打包、部署和管理。本文将深入介绍BentoML的功能和用法&#xff0c;提供详细的示例代码和解释&#xff0c;帮助你更好地理解和应用这个强大的工…

volatile-之小总结

凭什么我们Java写了一个volatile关键字&#xff0c;系统底层加入内存屏障&#xff1f;两者的关系如何勾搭&#xff1f; 内存屏障是什么&#xff1f; 是一种屏障指令&#xff0c;它使得CPU或编译器对屏障指令的前和后所发出的内存操作执行一个排序的约 束。也称为内存栅栏或栅…

低价商品采购API接口

采购商品地址http://sly.yizhaosulianyun.com/More/Push/888889?type3 低价商品采购API接口 1) 请求地址 http://sly.yizhaosulianyun.com/jd/keyWords 2) 调用方式&#xff1a;HTTP post 3) 接口描述&#xff1a; 低价商品采购接口 4) 请求参数: POST参数: 字段名称字段…

《Python机器学习原理与算法实现》学习笔记--一文掌握机器学习与Python的基础概念

机器学习常见的基础概念 根据输入数据是否具有“响应变量”信息&#xff0c;机器学习被分为“监督式学习”和“非监督式学习”。“监督式学习”即输入数据中即有X变量&#xff0c;也有y变量&#xff0c;特色在于使用“特征&#xff08;X变量&#xff09;”来预测“响应变量&am…

会泽一村民上山放羊吸烟引发森林火灾,AI科技急需关注

2023年4月&#xff0c;会泽县古城街道厂沟村委会望香台山林中发生了一场由疏忽引发的森林火灾。张某某在放羊时未完全熄灭烟头&#xff0c;导致7.33公顷的林地和草地被焚毁&#xff0c;直接经济损失高达29.097万元。这一事件再次凸显了日常生活中的安全隐患。 在这一背景下&…

GeoServer改造Springboot源码四(图层管理设计)

一、界面设计 图 1图层管理列表 图 2选择图层数据源 图 3添加图层 图 4编辑图层

如何决定产品功能的优先顺序:从 Scrum 过渡到 Shape Up

领导者应该决定要解决的问题的“内容”和“时间”&#xff08;而不是要实施的解决方案&#xff09;。产品团队成员应该可以自由地通过他们只能根据自己的专业知识和知识构思和执行的解决方案来定义“如何”。本文将指导我们从 Scrum 转向Shape Up&#xff0c;立即开始按时交货&…

芯片技术探索:了解构芯片的设计与制造之旅

芯片技术探索:了解构芯片的设计与制造之旅 一、引言 随着现代科技的飞速发展,芯片作为信息技术的核心,已经渗透到我们生活的方方面面。从智能手机、电视、汽车到医疗设备和工业控制系统,芯片在各个领域都发挥着至关重要的作用。然而,对于大多数人来说,芯片仍然是一个神秘…

11.30

1.设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace std;cl…

从setText处理来学习绘制流程

Android中TextView调用setText是会进行text文字的更新&#xff0c;是一个比较简单的画面变化&#xff0c;这可以作为一个出发点来查看绘制处理流程。这里来问问chatGPT&#xff0c;来查看大致流程 请讲讲Android中textView的setText处理流程 ChatGPT Poe 当你调用 textView.s…

【蓝桥杯选拔赛真题70】Scratch输入输出数字 少儿编程scratch图形化编程 蓝桥杯创意编程选拔赛真题解析

目录 scratch输入输出数字 一、题目要求 编程实现 二、案例分析 1、角色分析

如何绕过某讯手游保护系统并从内存中获取Unity3D引擎的Dll文件

某讯的手游保护系统用的都是一套&#xff0c;在其官宣的手游加固功能中有一项宣传是对比较热门的Unity3d引擎的手游保护方案&#xff0c;其中对Dll文件的保护介绍如下&#xff0c; “Dll加固混淆针对Unity游戏&#xff0c;对Dll模块的变量名、函数名、类名进行加密混淆处理&…

哪吒汽车拔头筹,造车新势力首家泰国工厂投产

中国造车新势力首家泰国工厂投产&#xff01;11月30日&#xff0c;哪吒汽车位于泰国的首家海外工厂——泰国生态智慧工厂正式投产下线新车&#xff0c;哪吒汽车联合创始人兼CEO张勇、哪吒汽车泰国合作伙伴BGAC公司首席执行官万查曾颂翁蓬素等出席仪式。首辆“泰国制造”的哪吒汽…

4、RTC 实时时钟Demo(STM32F407)

RTC是个独立的BCD定时器/计数器。RTC 提供一个日历时钟&#xff0c;两个可编程闹钟中断&#xff0c;以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。 (RTC实质&#xff1a;一个掉电(主电源)后还继续运行(由VBAT供电)的32位的向上计…

深入了解Java8新特性-日期时间API之TemporalAdjusters与TemporalAdjuster

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概10000多字&#xff0c;预计阅读时间长需要10分钟。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&…

js 获取数组的最大值与最小值

let arr [1, 2, 5, 8, 10, 100, -1] 1. 使用Math的静态方法max/min Math.max()函数返回给定的一组数中的最大值。 它的语法&#xff1a;Math.max(value1[, value2, ...]) 使用此方法&#xff0c;需要注意&#xff0c;如果没有参数的话&#xff0c;则返回-Infinity。如果有任一…

“消费增值:让每一笔消费创造更多价值“

亲爱的消费者朋友们&#xff0c;你们好&#xff01;今天&#xff0c;我要向你们揭示一种全新的消费理念——消费增值&#xff0c;让你的每一笔消费都变得更有价值&#xff01; 在传统的消费观念中&#xff0c;我们仅仅用金钱来购买物品或享受服务&#xff0c;之后这些物品和服…

无mac电脑生成uniapp云打包私钥证书的攻略

uniapp顾名思义是一个跨平台的开发工具&#xff0c;大部分uniapp的开发者&#xff0c;其实并没有mac电脑来开发&#xff0c;但是生成ios的证书&#xff0c;官网的教程却是需要mac电脑的&#xff0c;那么有没有办法无需mac电脑即可生成uniapp云打包的私钥证书呢&#xff1f; 下…

程序员养生之道

程序员养生之道——如何保持健康的生活方式 摘要&#xff1a; 随着互联网行业的快速发展&#xff0c;越来越多的人选择从事程序员这个职业。然而&#xff0c;长时间的工作和高强度的压力容易导致程序员出现亚健康状况&#xff0c;如头发稀疏、视力下降、肥胖等问题。因此&#…

从谷歌搜索结果出现 AI 生成的图片谈起:AI的利与弊

随着人工智能&#xff08;AI&#xff09;的不断发展&#xff0c;其应用领域也越来越广泛。谷歌搜索是现代人日常生活中的一个常用工具&#xff0c;经常用于获取各种信息。最近&#xff0c;谷歌搜索结果中甚至出现了由AI生成的图片&#xff0c;这引发了人们对AI技术的讨论。 首…