效果图
三部分
头部日历
uniapp的插件市场
zsy-calendar 仿钉钉打卡统计日历 支持周与月的滑动切换
效果非常nice,原理没咋看懂,总之非常牛掰
底层时间线
<!-- template-->
<view class="behind">
<view v-for="(item,index) in time_interval">
<!-- -->
<view class="row" >
<!-- 左侧时间 -->
<view style="width: 10%;color: #999999;">{{item}}</view>
<!-- 右侧底部时间线 -->
<view style="background-color: #eaeaea;width: 90%;height: 1rpx;"></view>
</view>
</view>
</view>
<!-- script-->
time_interval: ["00:00", "01:00", "02:00", "03:00", "04:00",
"05:00", "06:00", "07:00", "08:00", "09:00",
"10:00", "11:00", "12:00", "13:00", "14:00",
"15:00", "16:00", "17:00", "18:00", "19:00",
"20:00", "21:00", "22:00", "23:00", "24:00"
]
<!-- style-->
.behind {
position: relative;
display: flex;
flex-direction: column;
.row {
width: 100%;
height: 60rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
}
上层事务分布
<!-- template-->
<view
style="z-index:1; width: 70%;position: absolute; margin-left: 15%;margin-top: 30rpx;">
<view v-for="(item,index) in line" :key="index"
:style="{'z-index:':index+10,'height':item.length+'rpx','background-color': item.remark===0?'':item.color}"
@click="lookbook(item)">
<!-- {{countbook(item)}} -->
</view>
</view>
<!-- script-->
数据库存储的数据类型:
schedule={
"data": "2022-08-08",
"name": "测试用户",
"schedule": [{
"title": "开会", //标题不超过6个字
"start": "08:30",
"end": "11:30",
"remarks": "测试备注内容", //备注内容
"color": "red" //事件的颜色背景
},
{
"title": "吃饭", //标题不超过6个字
"start": "11:30",
"end": "12:30",
"remarks": "测试备注内容", //备注内容
"color": "blue" //事件的颜色背景
}]
}
data里面准备一个空数组:line:[]
处理数据类型的方法
measure() {
if (!this.schedule.schedule) {
return
}
// 获取已预约的时间段
this.timeData = JSON.parse(JSON.stringify(this.schedule.schedule))
// 总分钟数
this.sumTime = (parseInt(this.time_interval.slice(-1)) - parseInt(this.time_interval[0])) * 60;
//空时间段(无“业务”) timeData格式[],
if (this.isEmptyObject(this.timeData)) {
const s = {
"start": this.time_interval[0],
"end": this.time_interval.slice(-1),
"length": 1400,
"x": 0,
"remark": 0
}
this.line.push(s)
return
}
//排序 按开始时间顺序从前往后
this.timeData.sort(function(a, b) {
return a.start > b.start ? 1 : -1;
})
//处理数据,计算位置
this.timeData.forEach(item => {
item.length = Number(this.timeDifference(item.start, item.end))
item.x = Number(this.timeDifference(this.time_interval[0], item.start))
item.remark = 1 //0 可选;1 不可选(已被预约的)
})
// 处理预约数据之间的间隔
this.timeData.forEach((item, index) => {
if (index == 0) {
//第一项未到顶,增加空白项
if (item.x != 0) {
const s = {
"start": this.time_interval[0],
"end": item.start,
"length": item.x,
"x": 0,
"remark": 0
}
this.line.unshift(s)
}
this.line.push(item)
//只有一项
if (this.timeData.length == 1 && (item.x + item.length) < 1405) {
const s = {
"start": item.end,
"end": this.endTime,
"length": 1405 - (item.x + item.length),
"x": item.x + item.length,
"remark": 0
}
this.line.push(s)
console.log(this.line)
}
} else {
// 正常数据之间的间隔
if (item.x > (this.timeData[index - 1].x + this.timeData[index - 1].length)) {
const s = {
"start": this.timeData[index - 1].end,
"end": item.start,
"length": item.x - (this.timeData[index - 1].x + this.timeData[index - 1].length)+3,
"x": this.timeData[index - 1].x + this.timeData[index - 1].length,
"remark": 0
}
this.line.push(s)
}
this.line.push(item)
//最后一项未到底,增加空白项
if (this.timeData.length - 1 == index && item.x + item.length < 1405) {
const s = {
"start": item.end,
"end": this.time_interval.slice(-1),
"length": 1405 - (item.x + item.length),
"x": item.x + item.length,
"remark": 0
}
this.line.push(s)
}
}
})
}
点击事务,查看内容
lookbook(info) {
if (info.remark == 0) {
uni.showToast({
icon: 'none',
title: "点击预约"
})
} else {
console.log(info.title)
uni.showModal({
title: info.title,
content: '开始时间:' + info.start + "\n结束时间:" + info.end + '\n',
showCancel: false,
buttonText: '确定',
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
}
版权声明:本文为qq_51741194原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。