基于uni-app的 picker-view封装日期选择器 实现按月筛选

543 阅读1分钟

按月筛选:

image.png

基于ui组件 vk-uview-ui 修改 地址:vkuviewdoc.fsq.pub/components/…

u-popup 组件可自行修改其他组件

    <!--
 * @Author: hht 13598360631@163.com
 * @Date: 2023-01-03 16:57:09
 * @LastEditors: hht 13598360631@163.com
 * @LastEditTime: 2023-01-04 10:47:16
 * @FilePath: ''
 * @Description: '年月选择器'
-->
<template>
    <u-popup
        :maskCloseAble="maskCloseAble"
        v-model="myVisible"
        mode="bottom"
        @close="close"
        length="auto">
        <view class="u-picker-header" @touchmove.stop.prevent="">
				<view
					class="u-btn-picker u-btn-picker--tips"
					:style="{ color: cancelColor }"
					hover-class="u-opacity"
					:hover-stay-time="150"
					@click="close('cancel')"
				>
					{{ cancelText }}
				</view>
				<view class="u-picker__title">{{ title }}</view>
				<view
					class="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-view class="u-picker-view" :value="data.valueArr" @change="bindChange">
                <picker-view-column>
                    <view class="item" v-for="(item,index) in data.years" :key="index">{{item}}年</view>
                </picker-view-column>
                <picker-view-column>
                    <view class="item" v-for="(item,index) in data.months" :key="index">{{item}}月</view>
                </picker-view-column>
            </picker-view>
        </view>
	</u-popup>

</template>
<script setup >
import { reactive, getCurrentInstance,nextTick ,computed} from 'vue';
	import { onUnload, onLoad, onReady } from '@dcloudio/uni-app'
const props = defineProps({
    modelValue: {
        type: Boolean,
        default: false
    },
    // 是否允许通过点击遮罩关闭Picker
	maskCloseAble: {
		type: Boolean,
		default: true
	},
    // 遮罩的模糊度
	blur: {
		type: [String, Number],
		default: 0
	},
    // 取消按钮的文字
	cancelText: {
		type: String,
		default: "取消"
	},
	// 确认按钮的文字
	confirmText: {
		type: String,
		default: "确认"
	},
    // "取消"按钮的颜色
	cancelColor: {
		type: String,
		default: "#606266"
	},
	// "确定"按钮的颜色
	confirmColor: {
		type: String,
		default: "#2979ff"
	},
	// 年份开始时间
    startYear: {
			type: [String, Number],
			default: 2021
		},
	// 年份结束时间
	endYear: {
		type: [String, Number],
		default: 2050
	},
    // 默认显示的时间,2025-07-02
	defaultTime: {
		type: String,
		default: ""
	},
})

const data = reactive({
    visible: false,
    years: [],
    year: '',
    months: [],
    month: '',
    valueArr: [],
})

const emit = defineEmits(['update:modelValue','confirm'])

let myVisible = computed({
    get: function() {
        return props.modelValue
    },
    set: function(val) {
        emit('update:modelValue', val)
    }
})

onLoad(()=>{
    init()
})
	//日期时间处理
    function initTimeValue() {
		// 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号
		let fdate = props.defaultTime.replace(/\-/g, "/");
		fdate = fdate && fdate.indexOf("/") == -1 ? `2022/01/01 ${fdate}` : fdate;
		let time = null;
		if (fdate) time = new Date(fdate);
		else time = new Date();
		// 获取年日月时分秒
        data.years = []
        data.months = []
		data.year = time.getFullYear();
		data.month = Number(time.getMonth()) + 1;
        for (let i = 2020; i <= time.getFullYear(); i++) {
        data.years.push(i)
        }
        for (let i = 1; i <= 12; i++) {
            data.months.push(i)
        }
}
function init() {
    data.valueArr = [];
    data.time = props.defaultTime
    initTimeValue()
    data.valueArr.push(0);
	setYears();
    data.valueArr.push(0);
	setMonths();

}

function setYears() {
    // 获取年份集合
	data.years = generateArray(props.startYear, props.endYear);
	// 设置this.valueArr某一项的值,是为了让picker预选中某一个值
	data.valueArr.splice(data.valueArr.length - 1, 1, getIndex(data.years, data.year));
	console.log(data.valueArr,'this.valueArr');
}
function setMonths() {
    data.months = generateArray(1, 12);
	data.valueArr.splice(data.valueArr.length - 1, 1, getIndex(data.months, data.month));
}
		// 生成递进的数组
function generateArray(start, end) {
	// 转为数值格式,否则用户给end-year等传递字符串值时,下面的end+1会导致字符串拼接,而不是相加
	start = Number(start);
	end = Number(end);
	end = end > start ? end : start;
	// 生成数组,获取其中的索引,并剪出来
	return [...Array(end + 1).keys()].slice(start);
}
function getIndex (arr, val) {
	let index = arr.indexOf(val);
	// 如果index为-1(即找不到index值),~(-1)=-(-1)-1=0,导致条件不成立
	return ~index ? index : 0;
}
function bindChange(e) {
	const val = e.detail.value
    data.year = formatNumber(data.years[val[0]])
    data.month =formatNumber(data.months[val[1]])
    data.time = `${data.year}-${data.month}`
}
// 小于10前面补0,用于月份,日期,时分秒等
function formatNumber(num) {
	return +num < 10 ? "0" + num : String(num);
}
function getResult() {
    emit('confirm', data.time)
    close()
}
function close() {
    myVisible.value = false
}
</script>
<style scoped>
	.u-picker-view {
	height: 100%;
	box-sizing: border-box;
    }

    .item {
        line-height: 100rpx;
        text-align: center;
    }
    .u-picker-header {
        width: 100%;
        height: 2.8125rem;
        padding: 0 1.25rem;
        display: flex;
        justify-content: space-between;
        align-items: center;
        box-sizing: border-box;
        font-size: 0.9375rem;
        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-body {
	width: 100%;
	height: 500rpx;
	overflow: hidden;
	background-color: #fff;
}
</style>