uniapp 自定义级联多选下拉框

这是一个使用uniapp创建的自定义级联多选下拉框组件,涉及到年、月、周的选择。通过day.js处理时间相关逻辑,用户可以点击选择周度,组件会展示年份、月份和周数的选项,并能进行多选操作。点击确认后,会显示所选的时间范围。
摘要由CSDN通过智能技术生成

uniapp 自定义级联多选下拉框

    此案例需要引入day.js!!!
    day.min.js下载 也可自行npm安装后导入
    需要作为组件的请自己改下传入props!!!
    话不多说,先看功能 ↓
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<template>
	<view>
		<view class="content-box">
			<view class="time" @click="openTime" v-if="timeList!=0">{{timeList[0]}} +{{timeList.length}}</view>
				<view class="time" @click="openTime" v-else>请选择周度</view>
		</view>

		<view class="time-box" v-if="timeShow">
			<view class="box-head">
				<view class="cancel" @click="timeCancel">取消</view>
				<view class="confirm" @click="timeConfirm">确认</view>
			</view>
			<view style="display: flex;overflow-y: scroll;">
				<view class="left-box left-box-width">
					<view class="yearList-item" v-for="item,index in yearList" :key="item.key" @click="choiceYear(index)">
						<text :class="[{'is-selsect':index===tempYearIdx||item.isChecked}]">{{item.value}}</text>
					</view>
				</view>
				<view class="right-box right-box-width">
					<view  class="week-box">
						<view class="week-box-left">
							<view class="otherList-item" v-for="item,index in tempMonthList" :key="item.key"
								@click="choiceOtherTimeList(item.key,index)">
								<text :class="[{'is-selsect':tempOtherTimeIdx===index||item.isChecked}]">{{item.value}}</text>
							</view>
						</view>
						<view class="week-box-right">
							<view class="weekList-item" v-for="item,index in tempWeekList" :key="item.key"
								@click="choiceWeek(item.key)">
								<text :class="[{'is-selsect':item.isChecked}]">{{item.value}}</text>
							</view>
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import dayjs from '@/common/day.min.js';
	export default {
		name: "MultSelect",
		data() {
			return {
				time: '',
				timeShow: false,
				tempType: '',
				tempYearIdx: -1,
				tempOtherTimeIdx: -1,
				weekCount: '', //记录每月周的数量
				timeList: [],//存放数据的数组
				yearList: [],
				weekList: [],
				monthList: [],
				tempMonthList: [],
				tempWeekList:[],
			}
		},
		onReady() {
			this.timeList=[];
			this.optionInit();
		},
		methods: {
			
			//选择周度
			choiceWeek(week_key){
				if(this.tempOtherTimeIdx==-1){
					return ;
				}
				this.weekList=this.weekList.map(e=>{
					if(e.key==week_key){
						let newObj={...e,'isChecked':!e.isChecked}
						return newObj
					}
					return e
				})
				this.tempWeekList=this.tempWeekList.map(e=>{
					if(e.key==week_key){
						let newObj={...e,'isChecked':!e.isChecked}
						return newObj
					}
					return e
				})
				let year_key=week_key.split('-')[0];
				let month_key=week_key.slice(0,week_key.length-2);
				if(this.tempWeekList.some(e=>e.isChecked==true)){
					this.tempMonthList=this.tempMonthList.map(e=>{
						if(e.key==month_key){
							let newObj={...e,'isChecked':true}
							return newObj
						}
						return e
					})
					this.monthList=this.monthList.map(e=>{
						if(e.key==month_key){
							let newObj={...e,'isChecked':true}
							return newObj
						}
						return e
					})
					if(this.tempMonthList.some(e=>e.isChecked==true)){
						this.yearList=this.yearList.map(e=>{
							if(e.key==year_key){
								let newObj={...e,'isChecked':true}
								return newObj
							}
							return e
						})
					}else{
						this.yearList=this.yearList.map(e=>{
							if(e.key==year_key){
								let newObj={...e,'isChecked':false}
								return newObj
							}
							return e
						})
					}
				
				}else{
					this.tempMonthList=this.tempMonthList.map(e=>{
						if(e.key==month_key){
							let newObj={...e,'isChecked':false}
							return newObj
						}
						return e
					})
					this.monthList=this.monthList.map(e=>{
						if(e.key==month_key){
							let newObj={...e,'isChecked':false}
							return newObj
						}
						return e
					})
					if(this.tempMonthList.some(e=>e.isChecked==true)){
						this.yearList=this.yearList.map(e=>{
							if(e.key==year_key){
								let newObj={...e,'isChecked':true}
								return newObj
							}
							return e
						})
					}else{
						this.yearList=this.yearList.map(e=>{
							if(e.key==year_key){
								let newObj={...e,'isChecked':false}
								return newObj
							}
							return e
						})
					}
				}
			},
				//选择月份并初始化周
			choiceOtherTimeList(key,idx) {
				if(this.tempYearIdx==-1){
					return ;
				}
				this.tempOtherTimeIdx=idx;
				this.initWeekList(key);
			},
			initWeekList(month_key){
				this.tempWeekList=this.weekList.filter(v=>v.key.includes(month_key)&&v.key.length==month_key.length+2);
			},
			
			//选择年份并初始化月份
			choiceYear(idx) {
					this.tempYearIdx=idx;
					let year=this.yearList[idx].value;
					this.tempOtherTimeIdx=-1;
					this.initOtherTimeList(year);
					this.initWeekList(year+'-'+1);
			},
			initOtherTimeList(year) {
				this.tempMonthList=this.monthList.filter(v=>v.key.includes(year))
			},
			
			//配置项初始化
			optionInit(){
				let year = new Date().getFullYear();
				let month = new Date().getMonth() + 1;
				this.time = year + '-' + month;
				for (let i = 0; i < 10; i++) {
					let yearObj={};
					yearObj.key=year - i;
					yearObj.value=year - i;
					yearObj.isChecked=false;
					this.yearList.push(yearObj);
					for(let j=0;j<12;j++){
						let monthObj={};
						monthObj.key=(year-i)+'-'+(j+1)
						monthObj.value=j+1
						monthObj.isChecked=false;
						this.monthList.push(monthObj);
						let count=this.getWeekNumOfMonth(year - i,j+1);
						for(let k=0;k<count;k++){
							let weekObj={};
							weekObj.key=(year-i)+'-'+(j+1)+'-'+(k+1);
							weekObj.value='第'+(k+1)+'周'
							weekObj.isChecked=false;
							this.weekList.push(weekObj);
						}
					}
				}
				this.tempMonthList=this.monthList.slice(0,12);
				this.weekCount = this.getWeekNumOfMonth(year, month);
				this.tempWeekList=this.weekList.slice(0,this.weekCount);
			},
			timeCancel() {
				this.timeShow = false;
			
			},
			timeConfirm() {
					this.timeShow = false;
					this.timeList=[]
					this.weekList.forEach(e=>{
						if(e.isChecked){
							this.timeList.push(e.key);
						}
					})
					console.log(this.timeList);
			},
			getWeekNumOfMonth(year, month) {
				// 获取该月的最后一天
				const lastDayOfMonth = dayjs(`${year}-${month}`).endOf('month');
				// 当月最后一天是周几
				let week = lastDayOfMonth.day();
				// 当月有多少天
				let days = lastDayOfMonth.date();
				// 计算出该月有多少周
				return Math.ceil((days + 6 - week) / 7);
			},
			changeType(item, index) {
				this.tempTypeIndex = index;
				this.tempType = item;
			},
			cancel() {
				this.timeShow = false;
				this.typeShow = false;
			},
			confirm() {
				this.typeIndex = this.tempTypeIndex;
				this.type = this.tempType;
				this.timeShow = false;
				this.typeShow = false;
			},
			openType() {
				this.typeShow = !this.typeShow;
			},
			openTime() {
				this.timeShow = !this.timeShow;
			}
		}
	}
</script>

<style lang="scss" scoped>
	.week-box {
		display: flex;
		width: 100%;
		height: 100%;
	}

	.week-box-left,
	.week-box-right {
		width: 50%;
		height: 100%;
		overflow-y: scroll;
	}

	.left-box-width {
		width: 33% !important;
	}

	.right-box-width {
		width: 67% !important;
	}

	.left-box,
	.right-box {
		width: 50%;
		height: 350rpx;
		overflow-y: scroll;
		text-align: center;

	}

	.content-box {
		display: flex;

		.time,
		 {
			font-size: 28rpx;
			background-color: #ddd;
			border: 1rpx solid gray;
			padding: 8rpx 10rpx;
		}

		.time {
			margin-left: 20rpx;
		}
	}

	
	.yearList-item,
	.otherList-item,
	.weekList-item {
		height: 70rpx;
		line-height: 70rpx;
		font-size: 28rpx;
	}





	.is-selsect {
		color: deepskyblue;
	}

	.time-box,
	 {
		.box-head {
			position: relative;
			top: 0;
			display: flex;
			height: 60rpx;
			font-size: 28rpx;
			width: 100%;
			justify-content: space-between;
			align-items: center;

			.cancel,
			.confirm {
				padding: 8rpx 10rpx;

			}

			.confirm {
				color: deepskyblue;
			}
		}

		height: 400rpx;
		width: 100%;
		position: fixed;
		top:calc(100% - 400rpx);
		background-color: #ededed;

	}
</style>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值