uniapp uview扩展u-picker支持日历期间 年期间 月期间 时分期间组件
uniapp uview扩展u-picker支持日历期间 年期间 月期间 时分期间组件
日历期间、年期间、月期间及时分期间组件在不同的应用场景中发挥着重要的作用。这些组件通常用于表单、应用程序或网站中,以方便用户输入和选择特定的日期和时间范围。以下是这些组件的主要作用:
日历期间组件
日历期间组件允许用户从日历中选择一个或多个日期范围。这种组件在需要用户指定时间段的应用中非常有用,如会议安排、任务管理、假期申请等。其主要作用包括:
- 日期选择:提供直观的日历界面,让用户可以方便地选择起始日期和结束日期。
- 时间范围限制:可以设定可选择的日期范围,例如只能选择未来一周内的日期。
- 事件关联:在某些应用中,日历期间组件可以与事件管理功能相结合,让用户能够创建、编辑和删除与日期范围相关联的事件。
年期间组件
年期间组件通常用于需要用户指定整年或多年范围的情况。这种组件在财务报告、历史数据分析、年度计划等场景中尤为重要。其主要作用包括:
- 年份选择:允许用户选择特定的年份或年份范围。
- 数据聚合:在财务或数据分析应用中,年期间组件可以帮助用户快速聚合和查看特定年份或多年份的数据。
- 计划制定:在制定年度计划或进行长期规划时,年期间组件可以提供必要的时间框架。
月期间组件
月期间组件允许用户选择特定的月份或月份范围。这种组件在需要关注月度数据或计划的应用中非常有用,如月度预算、销售报告等。其主要作用包括:
- 月份选择:提供直观的月份选择界面,让用户可以方便地选择起始月份和结束月份。
- 数据对比:在需要对比不同月份数据的应用中,月期间组件可以帮助用户快速筛选出所需的数据范围。
- 计划执行:在制定月度计划或跟踪月度任务进度时,月期间组件可以提供清晰的时间线。
时分期间组件
时分期间组件专注于时间的选择,通常包括小时和分钟(有时也包括秒)。这种组件在需要精确到具体时间点的应用中非常重要,如会议安排、课程时间表等。其主要作用包括:
- 时间选择:允许用户选择特定的时间点或时间段。
- 时间间隔设置:在某些应用中,可以设定时间间隔(如每半小时一个选项),以便用户快速选择常见的时间点。
- 日程安排:在安排会议、约会或课程时间表时,时分期间组件可以确保时间的精确性和准确性。
综上所述,日历期间、年期间、月期间及时分期间组件在各自的应用场景中发挥着关键的作用,为用户提供了方便、直观且高效的时间选择和管理工具。
u-picker组件扩展支持上面类型区间组件
<!-- 选择器 -->
<template><u-popup:maskCloseAble="maskCloseAble"mode="bottom":popup="false"v-model="popupValue"length="auto":safeAreaInsetBottom="safeAreaInsetBottom"@close="close":z-index="uZIndex":blur="blur"><view class="u-datetime-picker"><view class="u-picker-header" @touchmove.stop.prevent=""><viewclass="u-btn-picker u-btn-picker--tips":style="{ color: cancelColor }"hover-class="u-opacity":hover-stay-time="150"@click="getResult('cancel')">{{ cancelText }}</view><view class="u-picker__title">{{ title }}</view><viewclass="u-btn-picker u-btn-picker--primary":style="{ color: moving ? cancelColor : confirmColor }"hover-class="u-opacity":hover-stay-time="150"@touchmove.stop=""@click.stop="getResult('confirm')">{{ confirmText }}</view></view><view class="u-picker-body"><picker-viewv-if="mode == 'region'":value="valueArr"@change="change"class="u-picker-view"@pickstart="pickstart"@pickend="pickend"><picker-view-column v-if="!reset && params.province"><view class="u-column-item" v-for="(item, index) in provinces" :key="index"><view class="u-line-1">{{ item.name }}</view></view></picker-view-column><picker-view-column v-if="!reset && params.city"><view class="u-column-item" v-for="(item, index) in citys" :key="index"><view class="u-line-1">{{ item.name }}</view></view></picker-view-column><picker-view-column v-if="!reset && params.area"><view class="u-column-item" v-for="(item, index) in areas" :key="index"><view class="u-line-1">{{ item.name }}</view></view></picker-view-column></picker-view><picker-viewv-else-if="mode == 'time'":value="valueArr"@change="change"class="u-picker-view"@pickstart="pickstart"@pickend="pickend"><picker-view-column v-if="!reset && params.year"><view class="u-column-item" v-for="(item, index) in years" :key="index">{{ item }}<text class="u-text" v-if="showTimeTag">年</text></view></picker-view-column><picker-view-column v-if="!reset && params.month"><view class="u-column-item" v-for="(item, index) in months" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">月</text></view></picker-view-column><picker-view-column v-if="!reset && params.day"><view class="u-column-item" v-for="(item, index) in days" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">日</text></view></picker-view-column><picker-view-column v-if="!reset && params.hour"><view class="u-column-item" v-for="(item, index) in hours" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">时</text></view></picker-view-column><picker-view-column v-if="!reset && params.minute"><view class="u-column-item" v-for="(item, index) in minutes" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">分</text></view></picker-view-column><picker-view-column v-if="!reset && params.second"><view class="u-column-item" v-for="(item, index) in seconds" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">秒</text></view></picker-view-column></picker-view><picker-viewv-else-if="mode.endsWith('Range')":value="valueArr"@change="change"class="u-picker-view"@pickstart="pickstart"@pickend="pickend"><picker-view-column v-if="!reset && params.year"><view class="u-column-item" v-for="(item, index) in years" :key="index">{{ item }}<text class="u-text" v-if="showTimeTag">年</text></view></picker-view-column><picker-view-column v-if="!reset && params.month"><view class="u-column-item" v-for="(item, index) in months" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">月</text></view></picker-view-column><picker-view-column v-if="!reset && params.day"><view class="u-column-item" v-for="(item, index) in days" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">日</text></view></picker-view-column><picker-view-column v-if="!reset && params.hour"><view class="u-column-item" v-for="(item, index) in hours" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">时</text></view></picker-view-column><picker-view-column v-if="!reset && params.minute"><view class="u-column-item" v-for="(item, index) in minutes" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">分</text></view></picker-view-column><picker-view-column v-if="!reset && params.second"><view class="u-column-item" v-for="(item, index) in seconds" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">秒</text></view></picker-view-column><picker-view-column v-if="!reset && params.year"><view class="u-column-item" v-for="(item, index) in years" :key="index">{{ item }}<text class="u-text" v-if="showTimeTag">年</text></view></picker-view-column><picker-view-column v-if="!reset && params.month"><view class="u-column-item" v-for="(item, index) in months" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">月</text></view></picker-view-column><picker-view-column v-if="!reset && params.day"><view class="u-column-item" v-for="(item, index) in days" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">日</text></view></picker-view-column><picker-view-column v-if="!reset && params.hour"><view class="u-column-item" v-for="(item, index) in hours" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">时</text></view></picker-view-column><picker-view-column v-if="!reset && params.minute"><view class="u-column-item" v-for="(item, index) in minutes" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">分</text></view></picker-view-column><picker-view-column v-if="!reset && params.second"><view class="u-column-item" v-for="(item, index) in seconds" :key="index">{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag">秒</text></view></picker-view-column></picker-view><picker-viewv-else-if="mode == 'selector'":value="valueArr"@change="change"class="u-picker-view"@pickstart="pickstart"@pickend="pickend"><picker-view-column v-if="!reset"><view class="u-column-item" v-for="(item, index) in range" :key="index"><view class="u-line-1">{{ getItemValue(item, "selector") }}</view></view></picker-view-column></picker-view><picker-viewv-else-if="mode == 'multiSelector'":value="valueArr"@change="change"class="u-picker-view"@pickstart="pickstart"@pickend="pickend"><picker-view-column v-if="!reset" v-for="(item, index) in range" :key="index"><view class="u-column-item" v-for="(item1, index1) in item" :key="index1"><view class="u-line-1">{{ getItemValue(item1, "multiSelector") }}</view></view></picker-view-column></picker-view></view></view></u-popup>
</template><script>
import provinces from "../../libs/address/provinces.json";
import citys from "../../libs/address/citys.json";
import areas from "../../libs/address/areas.json";
/*** picker picker弹出选择器* @description 此选择器有两种弹出模式:一是时间模式,可以配置年,日,月,时,分,秒参数 二是地区模式,可以配置省,市,区参数* @tutorial https://www.uviewui.com/components/picker.html* @property {Object} params 需要显示的参数,见官网说明* @property {String} mode 模式选择,region-地区类型,time-时间类型(默认time)* @property {String Number} start-year 可选的开始年份,mode=time时有效(默认1950)* @property {String Number} end-year 可选的结束年份,mode=time时有效(默认2050)* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)* @property {Boolean} show-time-tag 时间模式时,是否显示后面的年月日中文提示* @property {String} cancel-color 取消按钮的颜色(默认#606266)* @property {String} confirm-color 确认按钮的颜色(默认#19be6b)* @property {String} default-time 默认选中的时间,mode=time时有效* @property {String} confirm-text 确认按钮的文字* @property {String} cancel-text 取消按钮的文字* @property {String} default-region 默认选中的地区,中文形式,mode=region时有效* @property {String} default-code 默认选中的地区,编号形式,mode=region时有效* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)* @property {String Number} z-index 弹出时的z-index值(默认1075)* @property {Array} default-selector 数组形式,其中每一项表示选择了range对应项中的第几个* @property {Array} range 自定义选择的数据,mode=selector或mode=multiSelector时有效* @property {String} range-key 当range参数的元素为对象时,指定Object中的哪个key的值作为选择器显示内容* @event {Function} confirm 点击确定按钮,返回当前选择的值* @event {Function} cancel 点击取消按钮,返回当前选择的值* @example <u-picker v-model="show" mode="time"></u-picker>*/
export default {name: "u-picker",emits: ["update:modelValue", "input", "confirm", "cancel"],props: {// 通过双向绑定控制组件的弹出与收起value: {type: Boolean,default: false},modelValue: {type: Boolean,default: false},// picker中需要显示的参数params: {type: Object,default() {return {year: true,month: true,day: true,hour: false,minute: false,second: false,province: true,city: true,area: true,timestamp: true};}},// 当mode=selector或者mode=multiSelector时,提供的数组range: {type: Array,default() {return [];}},// 当mode=selector或者mode=multiSelector时,提供的默认选中的下标defaultSelector: {type: Array,default() {return [0];}},// 当 range 是一个 Array<Object> 时,通过 range-key 来指定 Object 中 key 的值作为选择器显示内容rangeKey: {type: String,default: ""},// 模式选择,region-地区类型,time-时间类型,selector-单列模式,multiSelector-多列模式mode: {type: String,default: "time"},// 年份开始时间startYear: {type: [String, Number],default: 1950},// 年份结束时间endYear: {type: [String, Number],default: 2050},// "取消"按钮的颜色cancelColor: {type: String,default: "#606266"},// "确定"按钮的颜色confirmColor: {type: String,default: "#19be6b"},// 默认显示的时间,2025-07-02 || 2025-07-02 13:01:00 || 2025/07/02defaultTime: {type: String,default: ""},// 默认显示的地区,可传类似["河北省", "秦皇岛市", "北戴河区"]defaultRegion: {type: Array,default() {return [];}},// 时间模式时,是否显示后面的年月日中文提示showTimeTag: {type: Boolean,default: true},// 地区编辑字符串areaCodes: {type: String,default: ""},// 默认显示地区的编码,defaultRegion和areaCode同时存在,areaCode优先,可传类似["13", "1303", "130304"]areaCode: {type: Array,default() {return [];}},safeAreaInsetBottom: {type: Boolean,default: false},// 是否允许通过点击遮罩关闭PickermaskCloseAble: {type: Boolean,default: true},// 弹出的z-index值zIndex: {type: [String, Number],default: 0},// 顶部标题title: {type: String,default: ""},// 取消按钮的文字cancelText: {type: String,default: "取消"},// 确认按钮的文字confirmText: {type: String,default: "确认"},// 遮罩的模糊度blur: {type: [String, Number],default: 0}},data() {return {popupValue: false,years: [],months: [],days: [],hours: [],minutes: [],seconds: [],year: 0,month: 0,day: 0,hour: 0,minute: 0,second: 0,//结束年月日pendyear: 0,pendmonth: 0,pendday: 0,pendhour: 0,pendminute: 0,pendsecond: 0,reset: false,startDate: "",endDate: "",rangeValue:"",valueArr: [],searchAreaCode:[],provinces: provinces,citys: citys[0],areas: areas[0][0],province: 0,city: 0,area: 0,moving: false // 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确};},mounted() {this.init();},computed: {valueCom() {// #ifndef VUE3return this.value;// #endif// #ifdef VUE3return this.modelValue;// #endif},propsChange() {// 引用这几个变量,是为了监听其变化return `${this.mode}-${this.defaultTime}-${this.startYear}-${this.endYear}-${this.defaultRegion}-${this.areaCode}-${this.areaCodes}`;},regionChange() {// 引用这几个变量,是为了监听其变化return `${this.province}-${this.city}`;},yearAndMonth() {return `${this.year}-${this.month}`;},uZIndex() {// 如果用户有传递z-index值,优先使用return this.zIndex ? this.zIndex : this.$u.zIndex.popup;}},watch: {propsChange() {this.reset = true;setTimeout(() => this.init(), 10);},// 如果地区发生变化,为了让picker联动起来,必须重置this.citys和this.areasregionChange(val) {this.citys = citys[this.province];this.areas = areas[this.province][this.city];},// watch监听月份的变化,实时变更日的天数,因为不同月份,天数不一样// 一个月可能有30,31天,甚至闰年2月的29天,平年2月28天yearAndMonth(val) {if (this.params.year) this.setDays();},// 微信和QQ小程序由于一些奇怪的原因(故同时对所有平台均初始化一遍),需要重新初始化才能显示正确的值valueCom:{immediate: true,handler(n){if (n) {this.reset = true;setTimeout(() =>{this.init()this.popupValue = n;} , 10);}else{this.popupValue = n;}}}},methods: {// 标识滑动开始,只有微信小程序才有这样的事件pickstart() {// #ifdef MP-WEIXINthis.moving = true;// #endif},// 标识滑动结束pickend() {// #ifdef MP-WEIXINthis.moving = false;// #endif},// 对单列和多列形式的判断是否有传入变量的情况getItemValue(item, mode) {// 目前(2020-05-25)uni-app对微信小程序编译有错误,导致v-if为false中的内容也执行,错误导致// 单列模式或者多列模式中的getItemValue同时被执行,故在这里再加一层判断if (this.mode == mode) {return typeof item == "object" ? item[this.rangeKey] : item;}},// 小于10前面补0,用于月份,日期,时分秒等formatNumber(num) {return +num < 10 ? "0" + num : String(num);},// 生成递进的数组generateArray: function(start, end) {// 转为数值格式,否则用户给end-year等传递字符串值时,下面的end+1会导致字符串拼接,而不是相加start = Number(start);end = Number(end);end = end > start ? end : start;// 生成数组,获取其中的索引,并剪出来return [...Array(end + 1).keys()].slice(start);},getIndex: function(arr, val) {let index = arr.indexOf(val);// 如果index为-1(即找不到index值),~(-1)=-(-1)-1=0,导致条件不成立return ~index ? index : 0;},//日期时间处理initTimeValue(prefix='') {// 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号let fdate = this.defaultTime.replace(/\-/g, "/");fdate = fdate && fdate.indexOf("/") == -1 ? `2020/01/01 ${fdate}` : fdate;let time = null;if (fdate) time = new Date(fdate);else time = new Date();// 获取年日月时分秒this[prefix+'year'] = time.getFullYear();this[prefix+'month'] = Number(time.getMonth()) + 1;this[prefix+'day'] = time.getDate();this[prefix+'hour'] = time.getHours();this[prefix+'minute'] = time.getMinutes();this[prefix+'second'] = time.getSeconds();},intValue(val){return parseInt(val)},initRangeTimeValue() {if(!this.defaultTime){this.initTimeValue('')this.initTimeValue('pend')}else{// 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号let values = this.defaultTime.split(" - ")if(this.mode=='yearRange'){this.year = this.intValue(values[0])this.pendyear = this.intValue(values[1])}else if(this.mode=='monthRange'){this.month = this.intValue(values[0])this.pendmonth = this.intValue(values[1])}else if(this.mode=='hourRange'){this.hour = this.intValue(values[0])this.pendhour = this.intValue(values[1])}else if(this.mode=='yearMonthRange'){let start = values[0]let pend = values[1]let yearMonth = start.split("-")this.year = this.intValue(yearMonth[0])this.month = this.intValue(yearMonth[1])let pendYearMonth = pend.split("-")this.pendyear = this.intValue(pendYearMonth[0])this.pendmonth = this.intValue(pendYearMonth[1])}else if(this.mode=='hourMinuteRange'){let start = values[0]let pend = values[1]let hourMinute = start.split(":")this.hour = this.intValue(hourMinute[0])this.minute = this.intValue(hourMinute[1])let pendHourMinute = pend.split(":")this.pendhour = this.intValue(pendHourMinute[0])this.pendminute = this.intValue(pendHourMinute[1])}}},init() {this.valueArr = [];this.reset = false;if (this.mode == "time") {this.initTimeValue();if (this.params.year) {this.valueArr.push(0);this.setYears();}if (this.params.month) {this.valueArr.push(0);this.setMonths();}if (this.params.day) {this.valueArr.push(0);this.setDays();}if (this.params.hour) {this.valueArr.push(0);this.setHours();}if (this.params.minute) {this.valueArr.push(0);this.setMinutes();}if (this.params.second) {this.valueArr.push(0);this.setSeconds();}}else if (this.mode.endsWith("Range")) {this.initRangeTimeValue();if (this.params.year) {this.valueArr.push(0);this.setYears('');}if (this.params.month) {this.valueArr.push(0);this.setMonths('');}if (this.params.day) {this.valueArr.push(0);this.setDays('');}if (this.params.hour) {this.valueArr.push(0);this.setHours('');}if (this.params.minute) {this.valueArr.push(0);this.setMinutes('');}if (this.params.second) {this.valueArr.push(0);this.setSeconds('');}if (this.params.year) {this.valueArr.push(0);this.setYears('pend');}if (this.params.month) {this.valueArr.push(0);this.setMonths('pend');}if (this.params.day) {this.valueArr.push(0);this.setDays('pend');}if (this.params.hour) {this.valueArr.push(0);this.setHours('pend');}if (this.params.minute) {this.valueArr.push(0);this.setMinutes('pend');}if (this.params.second) {this.valueArr.push(0);this.setSeconds('pend');}} else if (this.mode == "region") {if(this.areaCodes){this.searchAreaCode = this.areaCodes.split("-")}else{this.searchAreaCode = this.areaCode}if (this.params.province) {this.valueArr.push(0);this.setProvinces();}if (this.params.city) {this.valueArr.push(0);this.setCitys();}if (this.params.area) {this.valueArr.push(0);this.setAreas();}} else if (this.mode == "selector") {this.valueArr = this.defaultSelector;} else if (this.mode == "multiSelector") {this.valueArr = this.defaultSelector;this.multiSelectorValue = this.defaultSelector;}this.$forceUpdate();},// 设置picker的某一列值setYears(prefix='') {// 获取年份集合this.years = this.generateArray(this.startYear, this.endYear);// 设置this.valueArr某一项的值,是为了让picker预选中某一个值this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this[prefix+'year']));},setMonths(prefix='') {this.months = this.generateArray(1, 12);this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this[prefix+'month']));},setDays(prefix='') {let totalDays = new Date(this[prefix+'year'],this[prefix+'month'], 0).getDate();this.days = this.generateArray(1, totalDays);let index = 0;// 这里不能使用类似setMonths()中的this.valueArr.splice(this.valueArr.length - 1, xxx)做法// 因为this.month和this.year变化时,会触发watch中的this.setDays(),导致this.valueArr.length计算有误if (this.params.year && this.params.month) index = 2;else if (this.params.month) index = 1;else if (this.params.year) index = 1;else index = 0;// 当月份变化时,会导致日期的天数也会变化,如果原来选的天数大于变化后的天数,则重置为变化后的最大值// 比如原来选中3月31日,调整为2月后,日期变为最大29,这时如果day值继续为31显然不合理,于是将其置为29(picker-column从1开始)if (this[prefix+'day'] > this.days.length) this[prefix+'day'] = this.days.length;this.valueArr.splice(index, 1, this.getIndex(this.days, this[prefix+'day']));},setHours(prefix='') {this.hours = this.generateArray(0, 23);this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this[prefix+'hour']));},setMinutes(prefix='') {this.minutes = this.generateArray(0, 59);this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this[prefix+'minute']));},setSeconds(prefix='') {this.seconds = this.generateArray(0, 59);this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this[prefix+'second']));},setProvinces() {// 判断是否需要province参数if (!this.params.province) return;let tmp = "";let useCode = false;// 如果同时配置了defaultRegion和areaCode,优先使用areaCode参数if (this.searchAreaCode.length) {tmp = this.searchAreaCode[0];useCode = true;} else if (this.defaultRegion.length) tmp = this.defaultRegion[0];else tmp = 0;// 历遍省份数组匹配provinces.map((v, k) => {if (useCode ? v.code == tmp : v.name == tmp) {tmp = k;}});this.province = tmp;this.provinces = provinces;// 设置默认省份的值this.valueArr.splice(0, 1, this.province);},setCitys() {if (!this.params.city) return;let tmp = "";let useCode = false;if (this.searchAreaCode.length) {tmp = this.searchAreaCode[1];useCode = true;} else if (this.defaultRegion.length) tmp = this.defaultRegion[1];else tmp = 0;citys[this.province].map((v, k) => {if (useCode ? v.code == tmp : v.name == tmp) {tmp = k;}});this.city = tmp;this.citys = citys[this.province];this.valueArr.splice(1, 1, this.city);},setAreas() {if (!this.params.area) return;let tmp = "";let useCode = false;if (this.searchAreaCode.length) {tmp = this.searchAreaCode[2];useCode = true;} else if (this.defaultRegion.length) tmp = this.defaultRegion[2];else tmp = 0;areas[this.province][this.city].map((v, k) => {if (useCode ? v.code == tmp : v.name == tmp) {tmp = k;}});this.area = tmp;this.areas = areas[this.province][this.city];this.valueArr.splice(2, 1, this.area);},close() {this.$emit("input", false);this.$emit("update:modelValue", false);},// 用户更改picker的列选项change(e) {console.log(e.detail.value)this.valueArr = e.detail.value;let i = 0;if (this.mode == "time") {// 这里使用i++,是因为this.valueArr数组的长度是不确定长度的,它根据this.params的值来配置长度// 进入if规则,i会加1,保证了能获取准确的值if (this.params.year) this.year = this.years[this.valueArr[i++]];if (this.params.month) this.month = this.months[this.valueArr[i++]];if (this.params.day) this.day = this.days[this.valueArr[i++]];if (this.params.hour) this.hour = this.hours[this.valueArr[i++]];if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]];if (this.params.second) this.second = this.seconds[this.valueArr[i++]];}else if (this.mode == "region") {if (this.params.province) this.province = this.valueArr[i++];if (this.params.city) this.city = this.valueArr[i++];if (this.params.area) this.area = this.valueArr[i++];}else if (this.mode.endsWith("Range")) {this.rangeValue = this.getRangeValue()}else if (this.mode == "multiSelector") {let index = null;// 对比前后两个数组,寻找变更的是哪一列,如果某一个元素不同,即可判定该列发生了变化this.defaultSelector.map((val, idx) => {if (val != e.detail.value[idx]) index = idx;});// 为了让用户对多列变化时,对动态设置其他列的变更if (index != null) {this.$emit("columnchange", {column: index,index: e.detail.value[index]});}}},getTimeValue(i){let result = {}if (this.params.year) result.year = this.formatNumber(this.years[this.valueArr[i++]]|| 0);if (this.params.month) result.month = this.formatNumber(this.months[this.valueArr[i++]]|| 0);if (this.params.day) result.day = this.formatNumber(this.days[this.valueArr[i++]]|| 0);if (this.params.hour) result.hour = this.formatNumber(this.hours[this.valueArr[i++]]|| 0);if (this.params.minute) result.minute = this.formatNumber(this.minutes[this.valueArr[i++]]|| 0);if (this.params.second) result.second = this.formatNumber(this.seconds[this.valueArr[i++]]|| 0);return [result,i];},getRangeValue(){let i = 0;// 这里使用i++,是因为this.valueArr数组的长度是不确定长度的,它根据this.params的值来配置长度// 进入if规则,i会加1,保证了能获取准确的值let startValue = this.getTimeValue(i);let start = startValue[0];let endValue = this.getTimeValue(startValue[1]);let end = endValue[0];let rangeValue = ""if(this.mode=='yearMonthRange'){let startYear = start.year;let endYear = end.year;let startMonth = start.month;let endMonth = end.month;if((startYear>endYear)||(startYear<=endYear&&startMonth>endMonth)){uni.$u.toast('开始年月不能大于年月')return;}rangeValue = startYear+"-"+startMonth+" - "+ endYear+"-"+endMonth}else if(this.mode=='hourMinuteRange'){let startHour = start.hour;let startMinute = start.minute;let endHour = end.hour;let endMinute = end.minute;if((startHour>endHour)||(startHour<=endHour&&startMinute>endMinute)){uni.$u.toast('开始时间不能大于结束时间')return;}rangeValue = startHour+":"+startMinute+" - "+ endHour+":"+endMinute}else if(this.mode=='hourRange'){let startHour = start.hour;let endHour = end.hour;if(startHour>endHour){uni.$u.toast('开始时间不能大于结束时间')return;}rangeValue = startHour+" - "+endHour}else if(this.mode=='yearRange'){let startYear = start.year;let endYear = end.year;if(startYear>endYear){uni.$u.toast('开始年不能大于结束年')return;}rangeValue = startYear+" - "+ endYear}else if(this.mode=='monthRange'){let startMonth = start.month;let endMonth = end.month;if(startMonth>endMonth){uni.$u.toast('开始月不能大于结束月')return;}rangeValue = startMonth+" - "+endMonth}return rangeValue;},// 用户点击确定按钮getResult(event = null) {// #ifdef MP-WEIXINif (this.moving) return;// #endiflet result = {};// 只返回用户在this.params中配置了为true的字段if (this.mode == "time") {if (this.params.year) result.year = this.formatNumber(this.year || 0);if (this.params.month) result.month = this.formatNumber(this.month || 0);if (this.params.day) result.day = this.formatNumber(this.day || 0);if (this.params.hour) result.hour = this.formatNumber(this.hour || 0);if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);if (this.params.second) result.second = this.formatNumber(this.second || 0);if (this.params.timestamp) result.timestamp = this.getTimestamp();}else if (this.mode.endsWith("Range")) {if(!this.rangeValue){this.rangeValue = this.getRangeValue()}result.result = this.rangeValue}else if (this.mode == "region") {if (this.params.province) result.province = provinces[this.province];if (this.params.city) result.city = citys[this.province][this.city];if (this.params.area) result.area = areas[this.province][this.city][this.area];} else if (this.mode == "selector") {result = this.valueArr;} else if (this.mode == "multiSelector") {result = this.valueArr;}if (event) this.$emit(event, result);this.close();},// 获取时间戳getTimestamp() {// yyyy-mm-dd为安卓写法,不支持iOS,需要使用"/"分隔,才能二者兼容let time =this.year +"/" +this.month +"/" +this.day +" " +this.hour +":" +this.minute +":" +this.second;return new Date(time).getTime() / 1000;},// 获得数据源getDateSource() {return {provinces,citys,areas};},// 智能识别省市区regionDiscern(addressText){// 街道地址let address = "";// 省let province = {};// 市let city = {};// 区let area = {};if (!addressText) return { code: -1, msg: "地址文本不能为空" };addressText.trim(); // 去除前后空格// 省// 1.先找出省份,通过匹配前面两个字(中国34个省份中,前面两个字不会重复)let firstTwoKey = addressText.substring(0, 2); //字符串开始的两个字符// 所在省的下标let provinceIndex = -1;for (let i = 0; i < provinces.length; i++) {let { code, name } = provinces[i];if (name.indexOf(firstTwoKey) == 0) {province = { code, name };provinceIndex = i;break;}}if (provinceIndex == -1) return { code: -1, msg: `省份【${firstTwoKey}】没有找到,请输入正确的地址` };// 获取市let citysArr = citys[provinceIndex];// 所在市的下标let cityIndex = -1;for (let i = 0; i < citysArr.length; i++) {let { name, code } = citysArr[i];// 除去最后一个 市 字let cityName = name.substr(0, name.length - 1);// 用城市的名字去匹配 addressText 地址if (addressText.indexOf(cityName) > -1) {city = { code, name };cityIndex = i;break;}}if (cityIndex == -1) return { code: -1, msg: `地级市没有找到,请输入正确的地址` };// 区let areasArr = areas[provinceIndex][cityIndex];// 所在区的下标let areaIndex = -1;for (let i = 0; i < areasArr.length; i++) {let { code, name } = areasArr[i];// 区名(县名)一般为3个字,如江干区,有可能会简写成 江干// 区名(县名)为2个字时,不会简写,如蓉县let reg = name;if (name.length > 2) reg += `|${name.substr(0, name.length - 1)}`;// 查找地址中是否存在该区名let areaRegExp = new RegExp(reg);if (addressText.search(areaRegExp) > -1) {area = { code, name };// 详情地址address = addressText.replace(new RegExp(reg), "{{~}}").split("{{~}}")[1];areaIndex = i;break;}}if (areaIndex == -1) return { code: -1, msg: "县级市没有找到,请输入正确的地址" };let formatted_address = `${province.name}${city.name}${area.name}${address}`;let res = {code: 0,msg: "ok",data: {province, // 省city, // 市area, // 区address, // 街道地址formatted_address, // 完整格式化地址}};return res;},// 智能识别收货信息addressDiscern(text) {// 收货人姓名let name = "";// 收货人手机let mobile = "";// 街道地址let address = "";// 省let province = {};// 市let city = {};// 区let area = {};if (!text) return { code: -1, msg: "地址文本不能为空" };//let newText = text.replace(/[^\a-\z\A-\Z0-9\u4E00-\u9FA5\ ]/g,' ');let textArr = text.split(/[^\u4e00-\u9fa5a-zA-Z0-9+-()()]+/g).filter(v => v.length);if (textArr.length != 3) return { code: -1, msg: "地址格式不正确,请按姓名 手机号 收货地址格式。" };// 获取姓名和手机号let temp;let addressText; // 地址原文for (let [k, v] of textArr.entries()) {if (/^1[3,4,5,6,7,8,9][0-9]{9}$/.test(v)) {mobile = v;continue;}//记录第一次出现的字符串if (!temp) {temp = v;continue;}// 当前字符串的长度和之前字符串的长度的对比,进而确定姓名和地址信息temp.length > v.length? ((addressText = temp), (name = v)): ((addressText = v), (name = temp));}let positionRes = this.regionDiscern(addressText);if (positionRes.code !== 0) return positionRes;let res = {code: 0,msg: "ok",data: {name, // 姓名mobile, // 手机号position: positionRes.data, // 省市区街道信息}};return res;}}
};
</script><style lang="scss" scoped>
.u-datetime-picker {position: relative;z-index: 999;
}.u-picker-view {height: 100%;box-sizing: border-box;
}.u-picker-header {width: 100%;height: 90rpx;padding: 0 40rpx;display: flex;justify-content: space-between;align-items: center;box-sizing: border-box;font-size: 30rpx;background: #fff;position: relative;
}.u-picker-header::after {content: "";position: absolute;border-bottom: 1rpx solid #eaeef1;-webkit-transform: scaleY(0.5);transform: scaleY(0.5);bottom: 0;right: 0;left: 0;
}.u-picker__title {color: $u-content-color;
}.u-picker-body {width: 100%;height: 500rpx;overflow: hidden;background-color: #fff;
}.u-column-item {display: flex;align-items: center;justify-content: center;font-size: 32rpx;color: $u-main-color;padding: 0 8rpx;
}.u-text {font-size: 24rpx;padding-left: 8rpx;
}.u-btn-picker {padding: 16rpx;box-sizing: border-box;text-align: center;text-decoration: none;
}.u-opacity {opacity: 0.5;
}.u-btn-picker--primary {color: $u-type-primary;
}.u-btn-picker--tips {color: $u-tips-color;
}
</style>
组件调用
<template><view class="container container329152"><u-form-item class="diygw-col-24" label="时间" prop="udate"><u-input @click="showUdate = true" class="" placeholder="请选择" v-model="udate" type="select"></u-input><u-picker :defaultTime="udate" v-model="showUdate" mode="yearRange" :params="paramsUdate" @confirm="changeUdate"></u-picker></u-form-item><u-form-item class="diygw-col-24" label="时间" prop="udate4"><u-input @click="showUdate4 = true" class="" placeholder="请选择" v-model="udate4" type="select"></u-input><u-picker :defaultTime="udate4" v-model="showUdate4" mode="yearMonthRange" :params="paramsUdate4" @confirm="changeUdate4"></u-picker></u-form-item><u-form-item class="diygw-col-24" label="时间" prop="udate3"><u-input @click="showUdate3 = true" class="" placeholder="请选择" v-model="udate3" type="select"></u-input><u-picker :defaultTime="udate3" v-model="showUdate3" mode="hourRange" :params="paramsUdate3" @confirm="changeUdate3"></u-picker></u-form-item><u-form-item class="diygw-col-24" label="时间" prop="udate2"><u-input @click="showUdate2 = true" class="" placeholder="请选择" v-model="udate2" type="select"></u-input><u-picker :defaultTime="udate2" v-model="showUdate2" mode="hourMinuteRange" :params="paramsUdate2" @confirm="changeUdate2"></u-picker></u-form-item><view class="clearfix"></view></view>
</template><script>export default {data() {return {//用户全局信息userInfo: {},//页面传参globalOption: {},//自定义全局变量globalData: {},paramsUdate: {year: true,month: false,day: false,hour: false,minute: false,second: false},showUdate: false,udate: '',paramsUdate4: {year: true,month: true,day: false,hour: false,minute: false,second: false},showUdate4: false,udate4: '',paramsUdate3: {year: false,month: false,day: false,hour: true,minute: false,second: false},showUdate3: false,udate3: '',paramsUdate2: {year: false,month: false,day: false,hour: true,minute: true,second: false},showUdate2: false,udate2: ''};},onShow() {this.setCurrentPage(this);},onLoad(option) {this.setCurrentPage(this);if (option) {this.setData({globalOption: this.getOption(option)});}this.init();},methods: {async init() {},// 新增方法 自定义方法async testFunction(param) {let thiz = this;console.log(this.checkbox);},changeUdate(evt) {this.udate = evt.result;},changeUdate4(evt) {this.udate4 = evt.result;},changeUdate3(evt) {this.udate3 = evt.result;},changeUdate2(evt) {this.udate2 = evt.result;}}};
</script><style lang="scss" scoped>.container329152 {}
</style>
相关文章:

uniapp uview扩展u-picker支持日历期间 年期间 月期间 时分期间组件
uniapp uview扩展u-picker支持日历期间 年期间 月期间 时分期间组件 日历期间、年期间、月期间及时分期间组件在不同的应用场景中发挥着重要的作用。这些组件通常用于表单、应用程序或网站中,以方便用户输入和选择特定的日期和时间范围。以下是这些组件的主要作用&a…...

GAMES101(10~11节,几何)
Geometry implicit隐式几何表示: 函数f(x,y,z): 根据函数fn描述几何,遍历所有空间内 的点,如果带入xyz到函数f(x,y,z)结果0那就绘制这个点 如果xyz求值结果>0表示在几何外,0在表面,<0在几何内 构造几何csg(…...
家电制造的隐形守护者:矫平机确保材料完美无瑕
在家电制造业中,产品的美观和耐用性是消费者选择的关键因素。然而,在生产过程中,材料的翘曲问题往往成为影响产品质量的隐形杀手。幸运的是,矫平机的出现,为家电制造商提供了一个有效的解决方案,确保每一件…...
软件设计师考纲及笔记
1. 计算机系统知识(分值占比:10%,重要程度:★★★★☆) 1.1 计算机系统基础 计算机组成: 中央处理器(CPU):计算机的核心部件,执行指令并处理数据。内存&…...

基于SpringCloud的微服务框架
1. 服务架构演变 1.1 单体架构 开发部署方便,维护扩展难。 1.2 垂直分割 将应用拆分成多个垂直部分,每一部分负责一组相关功能。 1.3 SOA(Service-Oriented Architecture) 面向服务的架构,引入了服务的概念。通过…...

C++速通LeetCode简单第19题-只出现一次的数字
方法一:暴力求解,排序后两个两个比较,两者不同时前者为答案: class Solution { public:int singleNumber(vector<int>& nums) {if(nums.size() 1) return nums[0];list<int> l;int ans 0;for(int i 0;i< n…...
AutoSar AP中Proxy Class中Methods描述的总结
☞ 返回总目录 5.3.6 Methods(方法) Proxy Class 与方法包装类 代理类与方法成员:对于远程服务的每种方法,Proxy Class 包含特定于该方法的包装类成员。例如示例中有 Calibrate、Adjust 和 LogCurrentState 三种方法对应的成员。…...
如何在本地计算机中打开远程服务器的Jupyter notebook
1. 在你的本地计算机上打开终端。 2. 使用SSH命令创建一个隧道: ssh -L 8888:localhost:8888 your_usernameyour_server_ip 这里,your_username 是你的服务器用户名,your_server_ip 是你的服务器IP地址。 其中,-L 8888:localhos…...

实习项目|苍穹外卖|day11
Apache ECharts 前端技术。 营业额统计 还是比较简单的。 用户统计 订单统计 以上所有需求。难点在于对时间类的处理: // 接收格式 GetMapping("/turnoverStatistics")ApiOperation("营业额统计")public Result<TurnoverReportVO>…...

easy_cloudantivirus
0x00前言 必须安装在virtualbox 攻击机:kali 靶机 easy_cloudantivirus 链接: https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/ 0x01信息搜集 经过测试发现靶场IP为192.168.56.106 进一部对IP搜集信息 发现8080端口youhttp服务。…...
python中Web API 框架
Python 中有几个非常流行的 Web API 框架,它们让你可以轻松地构建和部署高效的 Web API。下面我将为你介绍几个最受欢迎的 Python Web API 框架,及其使用方法和特点。 1. FastAPI FastAPI 是一个现代、快速(非常高性能)的 Web 框…...

Linux(6)--CentOS目录
文章目录 1. 根目录2. cd目录切换命令3. CentOS目录介绍4. pwd命令介绍5. ls命令介绍5.1 ls5.2 ls -a5.3 ls -l 1. 根目录 Windows电脑的根目录是计算机(我的电脑),然后C盘、D盘。 Linux系统的根目录是/,我们可以使用cd /进入根目录,然后使…...
标准C++(二)
一、名字空间 什么是名字空间 在C语言中定义的全局变量、函数、结构、联合、枚举、枚举值、宏都在全局作用域下,所以当项目比较庞大时,非常容易造成命名冲突(以模块名作前缀、后缀),所以C中选择把全局作用域进行拆分…...

硬件工程师笔试面试——保险丝
目录 10、保险丝 10.1 基础 保险丝原理图 保险丝实物图 10.1.1 概念 10.1.2 保险丝的工作原理 10.1.3 保险丝的主要类型 10.1.4 保险丝的选择和使用注意事项 10.2 相关问题 10.2.1 保险丝的额定电流和额定电压是如何确定的? 10.2.2 保险丝的熔断速度对电路保护有何…...
本地安装Ollama+WebUI
本地安装OllamaWebUI B站教程地址:https://www.bilibili.com/video/BV1Kz421h7Jk/?spm_id_from333.337.search-card.all.click&vd_source42b07826977d09765ec11b9fa06715e5 一、下载Ollama https://ollama.com/download 支持mac、linux、windows 选择在ubu…...

请求响应-05.请求-日期参数JSON参数
一.日期参数 当浏览器发起的请求参数类型是日期参数时,我们通常使用LocalDateTime对象来接收,前面使用DateTimeFormat注解来完成日期的格式转换(日期时间格式有多种,需要哪种就设置为哪种:如yyyy-MM-dd HH:mm:ss&…...
CSS学习路线
CSS学习路线大全及面试常见题目可以归纳为以下几个部分: CSS学习路线大全 CSS基础 引入CSS的方式:外部样式表、内部样式表、内联样式。CSS选择器:包括ID选择器、类选择器、标签选择器、后代选择器、子选择器、相邻兄弟选择器、兄弟选择器、…...

Linux memcg lru lock提升锁性能
目录 内核关于per memcg lru lock的重要提交: 计算虚拟地址转换基本机制 问题背景 swap换入流程 时奎亮的per memcg lru lock分享视频 内核关于per memcg lru lock的重要提交: f9b1038ebccad354256cf84749cbc321b5347497 6168d0da2b479ce25a4647d…...
【spring】引入 Jackson 依赖 对java对象序列号和反序列化
Jackson Jackson 是一个非常流行的 Java 序列化/反序列化库,用于将 JSON 转换为 Java 对象,或者将 Java 对象转换为 JSON。要在你的 pom.xml 文件中引入 Jackson 依赖,你可以按照下面的步骤进行操作。引入 Jackson 依赖 通常,Jackson 核心库包含以下三个部分: jackson-dat…...
算法面经手撕系列(3)--手撕LayerNormlization
LayerNormlization 在许多的语言模型如Bert里,虽然都是说做的LayerNormlization,但计算均值和方差只会沿着channel维度做,并不是沿着seq_L和channel维度一起做,参考:BERT用的LayerNorm可能不是你认为的那个Layer Norm LayerNorm…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...