微信小程序手写时间间隔组件,可设置间隔时间一分钟,半小时,一小时的间隔

纯手写时间间隔组件

需求:小程序中可以根据时间段进行选择开始时间和结束时间,如:当前时间是09:00,
则我可以从9点开始选择时间,每半个小时为间隔,那么下一个时间就算9:30,10:00,依次类推
就像element-ui中有个时间选择器就可以根据自己设置的时间间隔去选择,可以0.5小时,1小时或者2.5小时的间隔进行选择
由于公司小程序用的是vant-ui来开发的,我去找vant的时间组件,发现没有这样的,所以决定自己开发一下这个组件

这是element-ui的选择时间

!!!注意:

由于公司用的是vant,所以弹窗按钮用的都是我们用vant自己封装的组件,
在这里就不展示弹窗组件还有按钮了,弹窗和按钮就得大家自己用自己的框架去显示了

看效果

在这里插入图片描述在这里插入图片描述
间隔一小时
在这里插入图片描述
提前30分钟和推迟30分钟 当前时间10:51
在这里插入图片描述在这里插入图片描述

创建 time-interval组件 如果你想全局使用则在app.json的usingComponents中添加你得组件地址

 "usingComponents": {"time-interval": "/components/time-interval/time-interval"}

创建好后就开始编码 HTML部分

<!-- 这个是我们自己封装的按钮组件 -->
<import src="../../static/templates/template.wxml"></import>
<!-- 工具类 -->
<wxs src="./util.wxs" module="computed" />
<!-- 这个是自己封装的弹窗组件 -->
<custom-popupcustomStyle="width: 100%;max-height: calc(100% - 148rpx); overflow: hidden; border-radius: 24rpx 24rpx 0 0;"hidden="{{!isShowTime}}" isShowPopup="{{isShowTime}}" title="{{title}}"isCloseOnClickOverlay="{{isCloseOnClickOverlay}}" bindhidePopup="hidePopup" bind:titleTap="titleTap">
<!-- 具体的时间间隔代码如下 --><view class="w-time_container"><view class="w-t_left" data-type="startOptions" bind:touchstart="onTouchStart" catch:touchmove="onTouchMove"bind:touchend="onTouchEnd" bind:touchcancel="onTouchEnd"><viewstyle="{{ computed.wrapperStyle({ offset:startOptions.offset, itemHeight, visibleItemCount, duration:startOptions.duration }) }}"><view class="w-time_row {{index===startOptions.currentIndex?'w-check_box':''}}"style="height: {{ itemHeight }}px" wx:for="{{timeList}}" wx:key="index" data-item="{{item}}"data-index="{{ index }}" data-type="startOptions" bind:tap="onClickItem">{{item.time}}</view></view></view><view class="w-t_right" data-type="endOptions" bind:touchstart="onTouchStart" catch:touchmove="onTouchMove"bind:touchend="onTouchEnd" bind:touchcancel="onTouchEnd"><viewstyle="{{ computed.wrapperStyle({ offset:endOptions.offset, itemHeight, visibleItemCount, duration:endOptions.duration }) }}"><viewclass="w-time_row {{index===endOptions.currentIndex?'w-check_box':''}} {{startTime.timeStamp>=item.timeStamp?'w-disabled':''}}"wx:for="{{timeList}}" wx:key="index" data-item="{{item}}" data-index="{{ index }}"data-type="endOptions" bind:tap="{{startTime.timeStamp>=item.timeStamp?'':'onClickItem'}}">{{item.time}}</view></view></view><view class="w-pick_mask" style="background-size: 100% 40%;"></view></view><!-- 这个是按钮组件 --><template is="iconBtn" data="{{btnText: '确定', btnTap: 'confirmTime'}}"></template>
</custom-popup>

js部分


/*** 获取当前天时间* @param param 【Y:年;M:月;D:日;h:小时;m:分钟;s:秒;】 默认精确到秒* @returns {*}*/
function getCurrentDate(param = 's', target = '') {var now = target ? new Date(toIosDate(target)) : new Date();var year = now.getFullYear(); //得到年份var month = now.getMonth(); //得到月份var date = now.getDate(); //得到日期var day = now.getDay(); //得到周几var hour = now.getHours(); //得到小时var minu = now.getMinutes(); //得到分钟var sec = now.getSeconds(); //得到秒month = month + 1;if (month < 10) month = "0" + month;if (date < 10) date = "0" + date;if (hour < 10) hour = "0" + hour;if (minu < 10) minu = "0" + minu;if (sec < 10) sec = "0" + sec;const arr = {'Y': year,'M': year + "-" + month,'D': year + "-" + month + "-" + date,'h': year + "-" + month + "-" + date + " " + hour,'m': year + "-" + month + "-" + date + " " + hour + ":" + minu,'s': year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec}return {year,month,day: date,hour,minu,sec,date: arr[param]};
}function range(num, min, max) {return Math.min(Math.max(num, min), max);
}function isObj(x) {const type = typeof x;return x !== null && (type === 'object' || type === 'function');
}
const DEFAULT_DURATION = 200;
let app = getApp();
let isIOS = /ios/ig.test(app.globalData.systemInfo.system);
/*** 判断是否是iso,ios的话时间格式会有问题得2023/09/13,以斜杠的格式传入* @param {时间} date */
function toIosDate(date) {return isIOS ? date.replace(/-/g, '/') : date
}
Component({options: {addGlobalClass: true,styleIsolation: "apply-shared"},/*** 组件的属性列表*/properties: {// 是否显示isShowTime: {type: Boolean,value: false,observer: 'initArr'},// 标题title: {type: String,value: '选择时间'},// 点击蒙层是否关闭弹窗isCloseOnClickOverlay: {type: Boolean,value: false},//间隔时间intervalTime: {type: Number,value: 1/60, //单位小时},//是否是推迟还是提前多少分钟 提前则大于0,推迟则小于0,且不能大于一天hasDelay: {type: Number,value: 0, //单位分钟},//选择的日期,默认当天的日期curDate: {type: String,valeu: getCurrentDate('D').date},//可见的选项个数visibleItemCount: {type: Number,value: 6},//选项高度itemHeight: {type: Number,value: 44}},/*** 组件的初始数据*/data: {startTime: {},endTime: {},timeList: [],startOptions: {startY: 0,startOffset: 0,duration: 0,offset: 0,currentIndex: 0},endOptions: {startY: 0,startOffset: 0,duration: 0,offset: 0,currentIndex: 0}},/*** 组件的方法列表*/methods: {initArr(nv, ov) {if (nv) {const {date,hour,minu,} = getCurrentDate('D')const w_date = this.properties.curDate ? (date === this.properties.curDate ? '' : `${this.properties.curDate} 00:00`) : `${date} ${hour}:${minu}`this.setData({timeList: this.createTime(getCurrentDate('D', w_date), this.properties.intervalTime)})this.setIndex(0, 'startOptions');this.setIndex(1, 'endOptions');}},createTime(target, h = 1) {const {hour,minu,date} = targetconst e_date = this.getRecentDate(1, this.properties.curDate)let arr = []let startStamp = new Date(toIosDate(date + ` ${hour}:${minu}`)).getTime()//是否是推迟还是提前多少分钟if (Math.abs(this.properties.hasDelay) > 0) {startStamp = startStamp + this.properties.hasDelay*60*1000} const endStamp = new Date(toIosDate(e_date + ' 00:00')).getTime()for (let i = startStamp; i < endStamp; i += (h * 60 * 60 * 1000)) {const res = this.formatDate(i)arr.push({time: res.time,date: res.date,dateM: res.dateM,timeStamp: i,disabled: false})}return arr},confirmTime() {if (!this.data.endTime.timeStamp) {return wx.showToast({title: '请选择结束时间',icon: 'none',})}this.triggerEvent('chooseInterver', {startTime: this.data.startTime,endTime: this.data.endTime})},//时间戳转换formatDate(target) {const date = new Date(target)let year = date.getFullYear();let months = date.getMonth() + 1;let month = (months < 10 ? '0' + months : months).toString();let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();let hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();let min = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();let sec = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();return {year: year.toString(),month,day,hours,min,sec,time: hours + ":" + min,date: year + "-" + month + "-" + day + " " + hours + ":" + min,dateM: year + "-" + month + "-" + day}},//计算当前时间几天后的数据getRecentDate(day, target) {var date1 = target ? new Date(toIosDate(target)) : new Date(),time1 = date1.getFullYear() + "-" + (date1.getMonth() + 1) + "-" + date1.getDate(); //time1表示当前时间var date2 = new Date(date1);date2.setDate(date1.getDate() + day);const y = date2.getFullYear();const m = (date2.getMonth() + 1) > 9 ? (date2.getMonth() + 1) : '0' + (date2.getMonth() + 1)const d = date2.getDate() > 9 ? date2.getDate() : '0' + date2.getDate()let h = date2.getHours() < 10 ? '0' + date2.getHours() : date2.getHours();let n = date2.getMinutes() < 10 ? '0' + date2.getMinutes() : date2.getMinutes();let s = date2.getSeconds() < 10 ? '0' + date2.getSeconds() : date2.getSeconds();return y + "-" + m + "-" + d;},hidePopup() {this.setData({[`startOptions.startY`]: 0,[`startOptions.startOffset`]: 0,[`startOptions.duration`]: 0,[`startOptions.currentIndex`]: 0,[`endOptions.startY`]: 0,[`endOptions.startOffset`]: 0,[`endOptions.duration`]: 0,[`endOptions.currentIndex`]: 0,})this.triggerEvent('close')},titleTap() {this.triggerEvent('titleTap')},getCount() {return this.data.timeList.length;},onTouchStart(event) {const options = event.currentTarget.dataset.typethis.setData({[`${options}.startY`]: event.touches[0].clientY,[`${options}.startOffset`]: this.data[options].offset,[`${options}.duration`]: 0,});},onTouchMove(event) {const options = event.currentTarget.dataset.typeconst deltaY = event.touches[0].clientY - this.data[options].startY;this.setData({[`${options}.offset`]: range(this.data[options].startOffset + deltaY,-(this.getCount() * this.properties.itemHeight),this.properties.itemHeight),});},onTouchEnd(event) {const options = event.currentTarget.dataset.typeif (this.data[options].offset !== this.data[options].startOffset) {this.setData({[`${options}.duration`]: DEFAULT_DURATION});const index = range(Math.round(-this.data[options].offset / this.data.itemHeight),0,this.getCount() - 1);this.setIndex(index, options);}},onClickItem(event) {const options = event.currentTarget.dataset.typeconst {index} = event.currentTarget.dataset;this.setIndex(index, options);},/*** 设置位置* @param {*} index 数组下标 位置* @param {*} options 数据类型*/setIndex(index, options) {const {data} = this;index = this.adjustIndex(index) || 0;const offset = -index * this.properties.itemHeight;if (index !== data[options].currentIndex) {this.setData({[`${options}.offset`]: offset,[`${options}.currentIndex`]: index,[`${options==='startOptions'?'startTime':'endTime'}`]: this.data.timeList[index]})//判断结束时间是否大于开始时间,是则选择否则为空if (options === 'endOptions') {if (this.data.startTime.timeStamp < this.data.timeList[index].timeStamp) {this.setData({endTime: this.data.timeList[index]})} else {this.setData({endTime: {}})}}else{this.setData({endTime: {}})}} else {this.setData({[`${options}.offset`]: offset,[`${options==='startOptions'?'startTime':'endTime'}`]: this.data.timeList[index]});}},adjustIndex(index) {const count = this.getCount();index = range(index, 0, count);for (let i = index; i < count; i++) {if (!this.isDisabled(this.data.timeList[i])) return i;}for (let i = index - 1; i >= 0; i--) {if (!this.isDisabled(this.data.timeList[i])) return i;}},isDisabled(option) {return isObj(option) && option.disabled;},}
})

css 部分

.w-time_container {position: relative;height: 600rpx;width: 100%;padding: 8rpx;box-sizing: border-box;display: flex;
}.w-t_left,
.w-t_right {width: 50%;height: 100%;display: flex;padding: 48rpx 0;flex-direction: column;align-items: center;box-sizing: border-box;overflow: hidden;
}.w-pick_mask{position: absolute;top: 0;left: 0;z-index: 1;width: 100%;height: 100%;background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4)), linear-gradient(0deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));background-repeat: no-repeat;background-position: top, bottom;transform: translateZ(0);pointer-events: none;
}.w-time_row {width: 100%;display: flex;align-items: center;justify-content: center;font-size: 32rpx;font-weight: 600;box-sizing: border-box;
}.w-check_box {color: #264AFF;
}
.w-disabled {color: #0A1B33B3;
}

工具类util.wxs

function addUnit(value) {if (value == null) {return undefined;}var REGEXP1 = getRegExp('^-?\d+(\.\d+)?$');return REGEXP1.test('' + value) ? value + 'px' : value;
}
var REGEXP2 = getRegExp('{|}|"', 'g');function keys(obj) {return JSON.stringify(obj).replace(REGEXP2, '').split(',').map(function (item) {return item.split(':')[0];});
}function kebabCase(word) {var newWord = word.replace(getRegExp("[A-Z]", 'g'), function (i) {return '-' + i;}).toLowerCase()return newWord;
}function isArray(array) {return array && array.constructor === 'Array';
}function style(styles) {if (isArray(styles)) {return styles.filter(function (item) {return item != null && item !== '';}).map(function (item) {return style(item);}).join(';');}if ('Object' === styles.constructor) {return keys(styles).filter(function (key) {return styles[key] != null && styles[key] !== '';}).map(function (key) {return [kebabCase(key), [styles[key]]].join(':');}).join(';');}return styles;
}function wrapperStyle(data) {var offset = addUnit(data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2);return style({transition: 'transform ' + data.duration + 'ms','line-height': addUnit(data.itemHeight),transform: 'translate3d(0, ' + offset + ', 0)',});
}module.exports = {wrapperStyle: wrapperStyle,
};

Attributes

参数说明类型可选值默认值
intervalTime间隔时间(单位小时)Number1/60(一分钟);30/60(30分钟); 1(1小时);2.5(两个半小时)1/60
hasDelay是否是推迟还是提前多少分钟 提前则大于0,推迟则小于0,且不能大于一天Number10(提前10分钟);-10(推迟10分钟)0
curDate选择的日期,默认当天的日期String2023-02-11或 2023-02-11 09:00:00当天时间

Events

参数说明类型参数返回值
chooseInterver选择时间结果Function-{starTime:resultTime,endTime:resultTime}

resultTime

prop说明
date日期+时分 2023-09-13 09:33
dateM日期没有时分 2023-09-13
time选择的时分 09:33
timeStamp选择date的时间戳 1694568780000

看过vant源码的会发现 我这里会有一部分vant的代码,确实是,我用了一下vant的时间选择器的样式代码,没办法时间紧迫写的样式达不到那种丝滑,只能凑合用

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

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

相关文章

【RocketMQ】消息的存储

当Broker收到生产者的消息发送请求时&#xff0c;会对请求进行处理&#xff0c;从请求中解析发送的消息数据&#xff0c;接下来以单个消息的接收为例&#xff0c;看一下消息的接收过程。 数据校验 封装消息 首先Broker会创建一个MessageExtBrokerInner对象封装从请求中解析到…

社区版IDEA导入Eclipse项目注意事项

经过正常导入教程之后。。。 有些jar包没有依赖导入&#xff0c;我这里直接把tomcat的lib全导入

【Spring Boot系列】- Spring Boot侦听器Listener

【Spring Boot系列】- Spring Boot侦听器Listener 文章目录 【Spring Boot系列】- Spring Boot侦听器Listener一、概述二、监听器Listener分类2.1 监听ServletContext的事件监听器2.2 监听HttpSeesion的事件监听器2.3 监听ServletRequest的事件监听器 三、SpringMVC中的监听器3…

骨传导耳机对人体有危险吗?会损害听力吗?

如果在使用骨传导耳机的时候控制好时间和音量&#xff0c;是不会对人体带来危险和造成伤害的。 下面跟大家解释一下为什么骨传导耳机对人体没有危害&#xff0c;最大的原因就是骨传导耳机不需要空气传导&#xff0c;而是通过颅骨传到听觉中枢&#xff0c;传输过程中几乎没有噪…

docker容器技术实战-2

03docker hub 首先注册上号&#xff1a; https://hub.docker.com/ 上传自己的镜像仓库 创建自己的仓库 webserver 拉取镜像 配置加速器 04搭建私有仓库 上传镜像 在主机1上 在主机2 上 激活内核选项 激活内核选项文件传输过去 配置使用非加密端口 05 docker私有仓库 仓库加…

langchain主要模块(二):数据连接

langchain2之数据连接 langchain1.概念2.主要模块模型输入/输出 (Model I/O)数据连接 (Data connection)链式组装 (Chains)代理 (Agents)内存 (Memory)回调 (Callbacks) 3.数据连接1.数据加载&#xff1a;2.文档分割&#xff1a;3.文档向量化&#xff1a;4.存储和检索向量数据:…

Webpack Sourcemap文件泄露漏洞

Webpack Sourcemap文件泄露漏洞 前言一、Webpack和Sourcemap1.1 什么是Webpack1.2 什么是Sourcemap 二、漏洞利用2.1 使用reverse-sourcemap工具2.1 直接看前端代码 三、漏洞挖掘漏洞修复 前言 Webpack主要是用于前端框架进行打包的工具&#xff0c;打包后形成.js.map文件&…

单例模式-饿汉模式、懒汉模式

单例模式&#xff0c;是设计模式的一种。 在计算机这个圈子中&#xff0c;大佬们针对一些典型的场景&#xff0c;给出了一些典型的解决方案。 目录 单例模式 饿汉模式 懒汉模式 线程安全 单例模式 单例模式又可以理解为是单个实例&#xff08;对象&#xff09; 在有些场…

LeetCode 35. 搜索插入位置

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 该题我们可以采用二分查找的方式&#xff0c;我们可以把数组分为&#xff0c;小于target的一边儿和大于等于target的一边儿。 当midleft(right-left)下标所对应的数大于等于targ…

多版本CUDA安装切换

系统中默认的安装CUDA为12.0&#xff0c;现在需要在个人用户下安装CUDA11.7。 CUDA 下载 CUDA官网下载 安装 Log file not open.Segmentation fault (core dumped)错误 将/tmp/cuda-installer.log删除即可。重新安装&#xff0c;去掉驱动的安装&#xff0c;设置Toolkit的安装…

骨科常用评估量表汇总,详细评分标准分享,建议收藏!

根据骨科医生的量表使用情况&#xff0c;笔者整理了9个常用的骨科量表&#xff0c;可在线评测并直接出结果&#xff0c;还可转发或生成二维码使用&#xff0c;或创建项目进行数据管理&#xff0c;有需要的小伙伴赶紧收藏&#xff01; Harris髋关节评分系统 Harris髋关节评分系…

3D点云处理:Opencv Pcl实现深度图转点云(附源码)

文章目录 0. 测试效果1. 代码实现文章目录:3D视觉个人学习目录0. 测试效果 处理结果1. 代码实现 文章中提供的深度图像,深度图像一般以.tiff和.png保存,可以通过Opencv中的 c v : : i m r

fabirc 将图像绘制原点定为图形内部

添加元素时&#xff0c;设置属性&#xff1a; originX: center, originY: center, 如我定义两个矩形&#xff1a; addrect () { // 矩形1var rect new fabric.Rect({top: 50,left: 100,width: 100,height: 70,fill: #F56C6C,strokeUniform: true // 限制边框宽度缩放})canva…

LINUX 网络管理

目录 一、NetworkManager的特点 二、配置网络 1、使用ip命令临时配置 1&#xff09;查看网卡在网络层的配置信息 2&#xff09;查看网卡在数据链路层的配置信息 3&#xff09;添加或者删除临时的网卡 4&#xff09;禁用和启动指定网卡 2、修改配置文件 3、nmcli命令行…

时序分解 | MATLAB实现基于SSA奇异谱分析的信号分解分量可视化

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 奇异谱分解奇异谱分析SSA 可直接替换txt数据运行 Matlab 1.包含3D分解效果图 频谱图等…

深圳唯创知音电子将参加IOTE 2023第二十届国际物联网展•深圳站

​ 2023年9月20~22日&#xff0c;深圳唯创知音电子将在 深圳宝安国际会展中心&#xff08;9号馆9B1&#xff09;为您全面展示最新的芯片产品及应用方案&#xff0c;助力传感器行业的发展。 作为全球领先的芯片供应商之一&#xff0c;深圳唯创知音电子一直致力于为提供高质量、…

分类预测 | Matlab实现基于BP-Adaboost数据分类预测

分类预测 | Matlab实现基于BP-Adaboost数据分类预测 目录 分类预测 | Matlab实现基于BP-Adaboost数据分类预测效果一览基本介绍研究内容程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于BP-Adaboost数据分类预测&#xff08;Matlab完整程序和数据&#xff09; 2.多特征输入…

K8S基础概念

1、Node Node作为集群中的工作节点&#xff0c;运行真正的应用程序&#xff0c;在Node上Kubernetes管理的最小运行单元是Pod。Node上运行着Kubernetes的Kubelet、kube-proxy服务进程&#xff0c;这些服务进程负责Pod的创建、启动、监控、重启、销毁、以及实现软件模式的负载均…

UMA 2 - Unity Multipurpose Avatar☀️二.概念介绍

文章目录 🟥 UMA核心🟧 UMA Data 数据类1️⃣ DNA2️⃣ Slots 插槽Overlays 纹理贴图🟨 Base Recipe 基础人形Recipes🟩 Wardrobe Recipes 服饰Recipes🟥 UMA核心 UMA核心组件是 DynamicCharacterAvatar ,后续我们跟插件交互的API,例如捏脸的参数,都是与之交互完成的…

基于Android的生鲜农产品商城交易设计与实现

摘 要 人们生活水平随着发展不断的提升&#xff0c;人们对生鲜产品消费比越来越依赖&#xff0c;都希望吃到新鲜的食品。消费的加大给生鲜了全新的供应链及销售模式&#xff0c;那种传统的生鲜配送模式也在发生着变化。生鲜系统电商平台在我国目前是属于盛行的电商行业&#x…