uniapp 时间表

效果图

html

<template>
	<view class="container">
		<view class="timetable">
			<view class="header">
				<view class="day" @click="handlePreviousDay">
					<uni-icons type="left" color="#333333" size="12"></uni-icons>
					前一天
				</view>
				<view class="date">{{nowTime}}</view>
				<view class="day" @click="handleNextDay">
					后一天
					<uni-icons type="right" color="#333333" size="12"></uni-icons>
				</view>
			</view>
			<view class="time_list">
				<!-- 时间表上时间显示的区域 -->
				<view 
				:class="['leave_box', item && item.my ? 'yellowBg' : 'blueBg']"
				v-for="(item,index) in tableList"
				:key="index"
				:style="{height: `${item.height}rpx`, top: `${item.top}rpx`}"
				>
				<text>名称</text>
				</view>
				<!-- 时间表表格 -->
				<view class="time_item" v-for="(item,index) in timeList" :key="index">
					<view class="time_item_text">{{item}}:00</view>
					<view class="time_item_leave"></view>
				</view>
			</view>
		</view>
	</view>
	
</template>

js

<script>
	import { createTime } from '@/utils/utils.js'
	export default {
		name:"timetable",
		data() {
			return {
				timeList: [
					'00','01','02','03','04','05','06','07','08','09','10','11',
					'12','13','14','15','16','17','18','19','20','21','22','23'
				],
				 // 当前日期
				nowTime: '', // xx年xx月xx日
				nowParams: '', // xx/xx/xx
				 // 列表单行高度
				li_H: 62,
				// 时间表
				renderSchedule: [
					{ formetter: '2023/03/09', time: '01:00-04:00', my: false },
					{ formetter: '2023/03/09', time: '08:00-10:10', my: false },
					{ formetter: '2023/03/09', time: '05:36-06:50', my: true },
					{ formetter: '2023/03/09', time: '17:30-19:30', my: true }
				],
				// 数据处理后渲染数据
				tableList: [],
			};
		},
		mounted(){
			let now = new Date()
			this.creationTime(now)
			this.processData()
		},
		methods:{
			// 获取当前日期
			creationTime(date){
				let timeParams = createTime(date)
				this.nowTime = `${timeParams.year}年${timeParams.month}月${timeParams.day}日 ${timeParams.weekday}`
				let timeP = createTime(date)
				this.nowParams = `${timeP.year}/${timeP.month}/${timeP.day}`
			},
			// 前一天
			handlePreviousDay(){
				let beforeDate = new Date(this.nowParams)
				beforeDate.setDate(beforeDate.getDate() - 1);
				this.creationTime(beforeDate)
			},
			// 后一天
			handleNextDay(){
				let afterDate = new Date(this.nowParams);
				afterDate.setDate(afterDate.getDate() + 1);
				this.creationTime(afterDate)
			},
			// 处理渲染的时间表数据
			processData(){
				this.renderSchedule.forEach(item => {
					let timedata = item.time.split('-');
					// 小时
					let startHour = timedata[0].slice(0, 2);
					let endHour = timedata[1].slice(0, 2);
					// 分钟
					let startMinute = timedata[0].slice(-2);
					let endMinute = timedata[1].slice(-2);
					// 开始时间的与结束时间相差几小时
					let myhour = Math.abs(endHour) - Math.abs(startHour);
					// 开始时间与结束时间相差几分钟
					let minute = Math.abs(endMinute) - Math.abs(startMinute);
					// dom高度
					let dom_height = dom_height = (myhour * this.li_H) + (minute * (this.li_H / 60));
					// console.log('高度', dom_height);
					item.height = parseInt(dom_height);
					// dom顶部偏移量
					let dom_top = (Math.abs(startHour) * this.li_H) + (Math.abs(startMinute) * (this.li_H / 60));
					// console.log('dom_top', dom_top);
					item.top = parseInt(dom_top);
				})
				this.tableList = this.renderSchedule;
			},
		},
	}
</script>

css

<style lang="less" scoped>
.container{
	padding: 20rpx 32rpx;
}
.timetable{
	border-radius: 20rpx 20rpx 0rpx 0rpx;
	border: 1px solid #DFE0EB;
	.header{
		height: 80rpx;
		background: rgba(223,224,235,0.3);
		padding:0 19rpx;
		display: flex;
		align-items: center;
		justify-content: space-between;
		border-bottom: 1px solid #DFE0EB;
		.day{
			font-size: 24rpx;
			font-family: 'SourceHanSansCN-Regular';
			font-weight: 400;
			color: #333333;
		}
		.date{
			font-size: 28rpx;
			font-family: 'Source Han Sans CN-Medium';
			font-weight: 500;
			color: #333333;
		}
	}
	.time_list{
		position: relative;
		.time_item{
			height: 61rpx;
			display: flex;
			border-bottom: 1px solid #DFE0EB;
			&:last-child{
				border-bottom: 0px solid #DFE0EB;
				.time_item_text,
				.time_item_leave{
					border-bottom: 0px solid #DFE0EB;
				}
			}
			.time_item_text{
				width: 84rpx;
				height: 61rpx;
				background: #F7F9FB;
				border-right: 1px solid #DFE0EB;
				text-align: center;
				line-height: 61rpx;
				font-size: 20rpx;
				font-family: 'SourceHanSansCN-Regular';
				font-weight: 400;
				color: #333333;
			}
			.time_item_leave{
				flex: 1;
				height: 61rpx;
			}
		}
		.leave_box{
			position: absolute;
			right: 0;
			width: calc(100% - 84rpx);
			font-size: 24rpx;
			font-family: 'SourceHanSansCN-Regular';
			font-weight: 400;
			color: #333333;
			text{
				line-height: 60rpx;
				padding-left: 20rpx;
			}
		}
		.yellowBg{
			background: rgba(255, 204, 0, 0.5);
		}
		.blueBg{
			background: rgba(0, 122, 255, 0.5);
		}
	}
}
		
</style>