当前位置: 首页 > news >正文

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>

相关文章:

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

需求背景解决效果视频效果balancedTimeElement.vue 需求背景 实现一个分片的时间间隔选择器&#xff0c;需要把显示时间段显示成图表&#xff0c;涉及一下集中数据转换 [“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, …...

PTA 魔法优惠券

7-83 魔法优惠券 分数 25 全屏浏览题目 作者 陈越 单位 浙江大学 在火星上有个魔法商店&#xff0c;提供魔法优惠券。每个优惠劵上印有一个整数面值K&#xff0c;表示若你在购买某商品时使用这张优惠劵&#xff0c;可以得到K倍该商品价值的回报&#xff01;该商店还免费赠送…...

P8A110-A120经典赛题

Web应用程序SQL Inject安全攻防 任务环境说明&#xff1a; 服务器场景&#xff1a;WebServ2003&#xff08;用户名&#xff1a;administrator&#xff1b;密码&#xff1a;空&#xff09;服务器场景操作系统&#xff1a;Microsoft Windows2003 Server 服务器场景安装服务/工…...

文件基础知识

计算机中的流&#xff1a;在C语言中将通过输入/输出设备&#xff08;键盘、内存、显示器、网络等&#xff09;之间的数据传输抽象表述为“流”。 1、文本流和二进制流 在文本流中输入输出的数据是一系列的字符&#xff0c;可以被修改在二进制流中输入输出数据是一系列字节&am…...

二叉树OJ题之二

今天我们一起来看一道判断一棵树是否为对称二叉树的题&#xff0c;力扣101题&#xff0c; https://leetcode.cn/problems/symmetric-tree/ 我们首先先来分析这道题&#xff0c;要判断这道题是否对称&#xff0c;我们首先需要判断的是这颗树根节点的左右子树是否对称&#xff0…...

MySql表中添加emoji表情

共五处需要修改。 语句执行修改&#xff1a; ALTER TABLE xxxxx CONVERT TO CHARACTER SET utf8mb4;...

【新手解答1】深入探索 C 语言:变量名、形参 + 主调函数、被调函数 + 类和对象 + 源文件(.c 文件)、头文件(.h 文件)+ 库

C语言的相关问题解答 写在最前面目录 问题1变量名与变量的关系与区别变量和数据类型形参&#xff08;形式参数&#xff09;的概念 问题2解析&#xff1a;主调函数和被调函数延伸解析&#xff1a;主调函数对于多文件程序的理解总结 问题3类和对象变量和数据类型变量是否为抽象的…...

2023最新的软件测试热点面试题(答案+解析)

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…...

NCo3.1(08) - Nco3 服务器端编程

本篇博文不再重复ABAP调用外部服务器的基础&#xff0c;只介绍 NCo3 开发的过程和要点。需要了解相关知识点的小伙伴们自行参考&#xff1a; SAP接口编程 之JCo3.0系列(06) - Jco服务器端编程 PyRFC 服务器端编程要点 创建项目 新建一个 Console 项目&#xff0c;选择 .Net …...

【代码随想录】算法训练计划36

贪心 1、435. 无重叠区间 题目&#xff1a; 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠 。 思路&#xff1a; 贪心&#xff0c;重叠个数&#xff0c;和射气球一样,重叠区间…...

Python (十五) 面向对象之多继承问题

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…...

广域网加速技术

摘要&#xff1a; 随着企业数字化转型快速发展&#xff0c;越来越多企业将IT系统、应用和服务部署到云上&#xff0c;以实现更高效、灵活的管理和使用。这就对广域网提出了更高的要求&#xff0c;而广域网线路往往存在带宽费用昂贵、服务质量不可靠等问题。为了改善用户体验&am…...

构建智能医患沟通:陪诊小程序开发实战

在医疗科技的浪潮中&#xff0c;陪诊小程序的开发成为改善医患沟通的创新途径之一。本文将介绍如何使用Node.js和Express框架构建一个简单而强大的陪诊小程序&#xff0c;实现患者导诊和医生咨询功能。 1. 安装Node.js和Express 首先确保已安装Node.js&#xff0c;然后使用以…...

插入区间[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个无重叠的 &#xff0c;按照区间起始端点排序的区间列表。在列表中插入一个新的区间&#xff0c;你需要确保列表中的区间仍然有序且不重叠&#xff08;如果有必要的话&#xff0c;可以合并区间&#xff09;。 示例 1&#x…...

Android Bitmap 模糊效果实现 (二)

文章目录 Android Bitmap 模糊效果实现 (二)使用 Vukan 模糊使用 RenderEffect 模糊使用 GLSL 模糊RS、Vukan、RenderEffect、GLSL 效率对比 Android Bitmap 模糊效果实现 (二) 本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134656140 最新更新地址 https:/…...

初识Java 18-4 泛型

目录 泛型存在的问题 在泛型中使用基本类型 实现参数化接口 类型转换和警告 无法实现的重载 基类会劫持接口 自限定类型 奇异递归类型 自限定 自限定提供的参数协变性 本笔记参考自&#xff1a; 《On Java 中文版》 泛型存在的问题 接下来讨论的&#xff0c;是在泛型…...

家政保洁预约小程序app开发特点有哪些?

家政预约服务小程序APP开发的特点介绍&#xff1b; 1. 低成本&#xff1a;用户通过手机APP下单&#xff0c;省去了中介费用&#xff0c;降低了雇主的雇佣成本。 2. 高收入&#xff1a;家政服务人员通过手机APP接单&#xff0c;省去了中介费用&#xff0c;从而提高了服务人员的…...

【JavaEE初阶】 HTTP响应报文

文章目录 &#x1f332;序言&#x1f38d;200 OK&#x1f340;404 Not Found&#x1f384;403 Forbidden&#x1f334;405 Method Not Allowed&#x1f38b;500 Internal Server Error&#x1f333;504 Gateway Timeout&#x1f332;302 Move temporarily&#x1f38d;301 Move…...

PTA: 螺旋矩阵

题目 所谓“螺旋矩阵”&#xff0c;是指对任意给定的N&#xff0c;将1到NN的数字从左上角第1个格子开始&#xff0c;按顺时针螺旋方向顺序填入NN的方阵里。本题要求构造这样的螺旋方阵。 格式 输入格式: 输入在一行中给出一个正整数N&#xff08;<10&#xff09;。 输出…...

SparkSQL远程调试(IDEA)

启动Intellij IDEA&#xff0c;打开spark源码项目&#xff0c;配置远程调试 Run->Edit Configuration 启动远程spark-sql spark-sql --verbose --driver-java-options "-Xdebug -Xrunjdwp:transportdt_socket,servery,suspendy,address5005"运行远程调试&#xf…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化

是不是受够了安装了oracle database之后sqlplus的简陋&#xff0c;无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话&#xff0c;配置.bahs_profile后也能解决上下翻页这些&#xff0c;但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可&#xff0c…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...

EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势

一、WebRTC与智能硬件整合趋势​ 随着物联网和实时通信需求的爆发式增长&#xff0c;WebRTC作为开源实时通信技术&#xff0c;为浏览器与移动应用提供免插件的音视频通信能力&#xff0c;在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能&#xff0c;对实时…...

统计学(第8版)——统计抽样学习笔记(考试用)

一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征&#xff08;均值、比率、总量&#xff09;控制抽样误差与非抽样误差 解决的核心问题 在成本约束下&#xff0c;用少量样本准确推断总体特征量化估计结果的可靠性&#xff08;置…...