canlendar.vue文件
<template>
<div>
<div class="calendar-box" :style="{ height: calHeight + 'px' }">
<p class="title">
<span>办事日历 </span>
</p>
<!-- 星期 -->
<ul class="calendar-head">
<li v-for="(item, index) in projectConfig.week_list" :key="index">{
{
item.text }}</li>
</ul>
<!-- 日历 -->
<calendarContent
ref="calendarSwiper"
:checkDate="currentDay"
@on-change="changeIndex"
@calendarHeight="calendarHeight">
<div
v-for="(month, index) in monthList"
:key="index"
class="month swiper-item">
<ul v-for="(week, weekindex) in month" :key="weekindex">
<li v-for="(day, dayindex) in week"
:class="{ ischecked: checkedDay == day.date,istoday: day.istoday,}"
@click.prevent.stop="chooseDay(day.year, day.month,day.day,day.othermonth,day.mode,day.thing)"
:key="dayindex" >
<div class="week-day"
:class="{ischecked: checkedDay == day.date,othermonth: day.othermonth,istoday: day.istoday,}">
<span class="one-day">
<i class="day" :class="day.istoday?'today':''">{
{
day.day }}</i>
</span>
<!-- 有事项标记 -->
<div class="thing" v-if="day.thing&&day.thing.infos&&day.thing.infos.length>0">
<a></a>
</div>
</div>
</li>
</ul>
</div>
</calendarContent>
</div>
<div class="thing-infos" v-if="dateThing&&dateThing.length>0">
<van-swipe :autoplay="3000" indicator-color="#87d7e8">
<van-swipe-item v-for="(item,index) in dateThing" :key="index">
<div v-for="info in item" :key="info.dates" class="mb-20">
<p >
<span class="title"><span class="vertical-bar"></span>今日事项:</span><span class="dis-in-block w-540">{
{
info.name}}</span>
</p>
<p>
<span class="title">地点:</span><span class="dis-in-block w-540">{
{
info.address}}</span>
</p>
<p>
<span class="title">时间:</span><span class="dis-in-block w-540">{
{
info.date}}</span>
</p>
</div>
</van-swipe-item>
</van-swipe>
</div>
<div v-else class="thing-infos" >
<div>
<p >
<span class="title"><span class="vertical-bar"></span>今日事项:</span><span class="dis-con w-540 ellipsis">---</span>
</p>
<p>
<span class="title">地点:</span><span class="dis-con w-540 ellipsis">---</span>
</p>
<p>
<span class="title">时间:</span><span class="dis-con w-540 ellipsis">---</span>
</p>
</div>
</div>
</div>
</template>
<script>
import calendarContent from "./swiper-monthorweek"
import projectConfig from "@/config/my/project-config"
export default {
components: {
calendarContent,
},
data() {
return {
projectConfig:projectConfig,
dispDate: new Date(),//当前时间
today: new Date(),//当前时间
currentDay: new Date(),//当前时间
monthList: [],//月份
checkedDay: "0000-00-00",//选中的时间
canClick: true,
calHeight: "", //日历外框高度,自适应要用到
dateThing:[],//事项
things:[
{
date:"2020-11-11",
infos:[
{
title:"人才招聘001",
address:"苏州市吴中区",
dates:"2020-11-11 09:00-18:00"
},
{
title:"人才招聘002",
address:"苏州市吴中区",
dates:"2020-11-11 09:00-18:00"
}
]
},
{
date:"2020-11-15",
infos:[
{
title:"人才招聘会人才",
address:"苏州市昆山市",
dates:"2020-11-15 09:00-18:00"
}
]
},
{
date:"2020-11-14",
infos:[
{
title:"人才招聘004",
address:"苏州市吴中区",
dates:"2020-11-14 09:00-18:00"
},
{
title:"人才招聘005",
address:"苏州市工业园区",
dates:"2020-11-14 09:00-18:00"
}
]
},
{
date:"2020-11-18",
infos:[
{
title:"人才招聘004",
address:"苏州市吴中区",
dates:"2020-11-18 09:00-18:00"
},
{
title:"人才招聘005",
address:"苏州市工业园区",
dates:"2020-11-18 09:00-18:00"
}
]
},
{
date:"2020-12-11",
infos:[
{
title:"人才招聘004",
address:"苏州市吴中区",
dates:"2020-12-11 09:00-18:00"
},
{
title:"人才招聘005",
address:"苏州市工业园区",
dates:"2020-12-11 09:00-18:00"
}
]
}
],
};
},
computed: {
/**
* 当前选中日期
*/
formateTime() {
// 标准时间转xxxx年xx月xx日
return this.formatDateTime(this.dispDate);
},
},
created() {
this.todayDate();
this.get3month();
},
mounted(){
this.getJobFairs(new Date().getTime())
},
methods: {
/**
* 日历高度
* @param newVal 日历动态高度
*/
calendarHeight(newVal) {
this.calHeight = newVal;
},
/**
* 获取今天日期
*/
todayDate() {
this.checkedDay = this.formatDateTime(this.today);
},
/**
* 选中某一天
* @param year 年
* @param month 月
* @param day 日
* @param othermonth 其他月份,当前月前面空值
* @param mode 类型,'month','week'
* @param thing 事项
*/
chooseDay(year, month, day, othermonth, mode,thing) {
// 为了PC端点击事件和移动冲突
if (!this.canClick) return;
this.currentDay = new Date(year, month, day);//标准时间
this.checkedDay = this.format(year, month, day);//"2020-11-11"
let timestamp = new Date(this.checkedDay).getTime();
this.getJobFairs(timestamp);
if (othermonth && mode == "month") {
var tmpDt = new Date(
this.dispDate.getFullYear(),
this.dispDate.getMonth() - othermonth,
0
);
var maxday = tmpDt.getDate();
var days = maxday < day ? maxday : day;
this.dispDate = new Date(year, month - othermonth, days);
this.changeIndex(othermonth, false, true);
} else if (othermonth && mode == "week") {
this.dispDate = this.currentDay;
} else {
this.dispDate = this.currentDay;
}
},
/**
* 转换时间格式
* @param date 标准时间
*/
formatDateTime(date) {
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? "0" + m : m;
var d = date.getDate();
d = d < 10 ? "0" + d : d;
var h = date.getHours();
var minute = date.getMinutes();
minute = minute < 10 ? "0" + minute : minute;
return y + "-" + m + "-" + d;
},
/**
* 转换时间
* @param year 年
* @param month 月
* @param day 日
*/
format(year, month, day) {
month++;
month < 10 && (month = "0" + month);
day < 10 && (day = "0" + day);
return year + "-" + month + "-" + day;
},
/**
* 转换时间格式
* @param timestamp 时间戳
*/
timestampToTime(timestamp) {
var date = new Date();//时间戳为10位需*1000,时间戳为13位的话不需乘1000
var Y = date.getFullYear() + '-';
var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
var D = (date.getDate() < 10 ? '0'+date.getDate() : date.getDate()) + ' ';
var h = (date.getHours() < 10 ? '0'+date.getHours() : date.getHours()) + ':';
var m = (date.getMinutes() < 10 ? '0'+date.getMinutes() : date.getMinutes()) ;
var s = ':'+ (date.getSeconds() < 10 ? '0'+date.getSeconds() : date.getSeconds());
let strDate = Y+M+D+h+m;
return strDate;
},
/**
* 获取星期
* @param year 为选中当天的年
* @param month 为选中当天的月
* @param day 为选中当天的日
*/
getWeek(year, month, day) {
var dt = new Date(year, month, day);
var weekArr = [];
var dtFirst = new Date(year, month, day - ((dt.getDay() + 6) % 7));
var week = [];
//循环选中当天所在那一周的每一天
for (var j = 0; j < 7; j++) {
var newdt = new Date(
dtFirst.getFullYear(),
dtFirst.getMonth(),
dtFirst.getDate() + j
);
var years = newdt.getFullYear();
var months = newdt.getMonth();
var days = newdt.getDate();
week.push({
mode: "week",
day: days,
year: years,
month: months,
date: this.format(years, months, days),
//日历要显示的其他内容
thing: this.ifOrder(years, months, days),
istoday:
this.today.getFullYear() == years &&
this.today.getMonth() == months &&
this.today.getDate() == days
? true
: false,
ischecked: false,
othermonth: months != month,
});
}
weekArr.push(week);
return weekArr;
},
/**
* 创建单月历
* @param year 年
* @param month 月
*/
getMonth(year, month) {
var monthArr = [];
var dtFirst = new Date(year, month, 1); //每个月第一天
var dtLast = new Date(year, month + 1, 0); //每个月最后一天
var monthLength = dtLast.getDate() - dtFirst.getDate() + 1;
var daylist = [];
var space = (dtFirst.getDay() - 1 + 7) % 7; //月历前面空格
for (var i = -space; i < 36; i += 7) {
var week = [];
for (var j = 0; j < 7; j++) {
var day = i + j + 1;
if (day > 0 && day <= monthLength) {
week.push({
mode: "month",
day: day,
year: year,
month: month,
date: this.format(year, month, day),
//日历要显示的其他内容
thing: this.ifOrder(year, month, day),
istoday:
this.today.getFullYear() == year &&
this.today.getMonth() == month &&
this.today.getDate() == day
? true
: false,
ischecked: false,
});
} else {
//其它月份
var newdt = new Date(year, month, day);
var years = newdt.getFullYear();
var months = newdt.getMonth();
var days = newdt.getDate();
week.push({
mode: "month",
day: days,
year: years,
month: months,
date: this.format(year, month, day),
thing: this.ifOrder(year, month, day),
istoday:
this.today.getFullYear() == years &&
this.today.getMonth() == months &&
this.today.getDate() == days
? true
: false,
ischecked: false,
othermonth: day <= 0 ? -1 : 1,
});
}
}
monthArr.push(week);
}
return monthArr;
},
/**
* 返回该天事项
* @param year 年
* @param month 月
* @param day 日
*/
ifOrder(year, month, day) {
let dateTime = this.format(year, month, day);
let dateItem = {
};
this.things.map(item=>{
if(dateTime==item.date){
dateItem = item;
}
})
return dateItem;
},
/**
* 获取三个月
*/
get3month() {
var year = this.dispDate.getFullYear();
var month = this.dispDate.getMonth();
this.monthList = [];
this.monthList.push(this.getMonth(year, month - 1));
this.monthList.push(this.getMonth(year, month));
this.monthList.push(this.getMonth(year, month + 1));
},
/**
* 获取三周
*/
get3week() {
var year = this.dispDate.getFullYear();
var month = this.dispDate.getMonth();
var day = this.dispDate.getDate();
this.monthList = [];
this.monthList.push(this.getWeek(year, month, day - 7));
this.monthList.push(this.getWeek(year, month, day));
this.monthList.push(this.getWeek(year, month, day + 7));
},
/**
* 左右移动
* @param index 月的index
* @param isWeek 是否显示周
* @param isClick 移动不可点击
*/
changeIndex(index, isWeek, isClick = false) {
if (index) {
if (isWeek) {
this.dispDate = new Date(
this.dispDate.getFullYear(),
this.dispDate.getMonth(),
this.dispDate.getDate() + 7 * index
);
this.checkedDay = this.format(
this.dispDate.getFullYear(),
this.dispDate.getMonth(),
this.dispDate.getDate()
);
this.currentDay = this.dispDate;
this.get3week();
} else {
var tmpDt = new Date(
this.dispDate.getFullYear(),
this.dispDate.getMonth() + index,
0
);
var maxday = tmpDt.getDate();
var days =maxday < this.dispDate.getDate() ? maxday : this.dispDate.getDate();
this.dispDate = new Date(
this.dispDate.getFullYear(),
this.dispDate.getMonth() + index,
days
);
if (!isClick) {
this.checkedDay = this.format(
this.dispDate.getFullYear(),
this.dispDate.getMonth(),
this.dispDate.getDate()
);
}
this.get3month();
}
this.getJobFairs(new Date(this.checkedDay).getTime())
this.$refs.calendarSwiper.moveChange();
}
},
/**
* 查询事项列表
* @param timestamp 时间戳
*/
getJobFairs(timestamp) {
this.loading = true;
axios.get(
`/jobFairs?time=${
timestamp}`
).then(res => {
this.dateThing = [];
var arr = [];
this.loading = false;
if (res.data && res.data.response) {
let response = res.data.response;
var itemData = response.data;
itemData.map(item => {
item.date =this.timestampToTime(item.hold_start_time );
item.enddate = this.timestampToTime(item.hold_end_time);
});
arr = arr.concat(itemData);
for(var i=0;i<arr.length;i+=2){
this.dateThing.push(arr.slice(i,i+2));
}
}
}).catch(e => {
if (e.data && e.data.errorCode) {
this.$toast.fail(dictionary[e.data.errorCode])
} else {
this.$toast.fail(language.error_500)
}
});
},
},
};
</script>
<style src="@/assets/css/calendar/common.css" scoped></style>
swiper-monthorweek.vue文件
<template>
<div class="calendar-body">
<p @click.prevent="toggleMove()" class="select-status">{
{
calendarHeight=='-100'||calendarHeight=='200'?'本月':'本周'}}</p>
<transition name="fade">
<div class="calendar-boxs" ref="calendar" :style="{height: calendarHeight == -100 ? calendarHeight+'px':'200px' }"
@touchstart.stop="moveStart"
@touchend.stop="moveEnd"
@touchmove.prevent="move">
<div class="calendar-s-box" :class="{transition:transition}" :style="{transform: 'translate3d('+calendarMove.x+'px,'+calendarMove.y+'px,0px)'}" >
<slot></slot>
</div>
</div>
</transition>
</div>
</template>
<script>
export default {
props:['checkDate'],
data(){
return{
transition:true,//是否显示动画
calendarHeight:-100, //日历的高度
calendarMove:{
x:0,y:0},
moveStartX:0, //开始移动的位置x轴
moveStartY:0, //开始移动的位置y轴
moveMode:1, //移动方式,1左右移动,2上下移动
canChangeMode:true, //是否可以改变移动方式
moveStartCalendarHeight:0, //开始移动的高度初始值
canMove:false, //是否触发move事件
itemWidth:0, //窗口的宽度
moveIndex:0, // 左右移动 1 向右移动-1向左移动
lineNum:0, // 选中或今天是第几行的周
isWeek:true, //是否是周历模式
}
},
created(){
//初始化日历宽度和lineNum
this.itemWidth = window.innerWidth
this.lineNum = this.calcLineNum(this.checkDate)
},
watch:{
/**
*监听当天
*@param val 当前天
*/
checkDate(val){
if(val){
this.lineNum = this.calcLineNum(val)
}
},
/**
*监听日历高度
*@param newVal height
*/
calendarHeight(newVal){
this.$emit('calendarHeight',newVal);
}
},
mounted(){
//初始化为周历
this.moveInit(false);
},
methods:{
/**
* PC端为了鼠标移出日历后不能触发mouseup事件而触发的事件
* @param e event
*/
moveEndPcOne(e){
if(this.canMove){
this.moveEndPc(e)
}
},
/**
* pc端开始移动
* @param e event
*/
moveStartPc(e){
if(!ISPC)return
this.moveStart(e)
},
/**
* pc端移动
* @param e event
*/
movePc(e){
if(!ISPC)return
this.move(e)
},
/**
* pc端结束移动
* @param e event
*/
moveEndPc(e){
if(!ISPC)return
this.moveEnd(e)
},
/**
* 手机端端开始移动
* @param e event
*/
moveStart(e){
var touch;
if(e.changedTouches){
touch = e.changedTouches[0];
}else{
touch = e
}
this.moveStartX = touch.clientX
this.moveStartY = touch.clientY
this.moveStartCalendarHeight = this.calendarHeight
this.canMove = true
this.moveMode = 0
this.$parent.canClick = true
},
/**
* 切换月或周
* @param e event
*/
toggleMove(e){
if(this.calendarHeight == 100){
this.calendarHeight = 200;
this.moveInit(true)
setTimeout(()=>{
this.$parent.get3month()
},500)
}else{
this.calendarHeight = 100;
this.moveInit(false)
}
},
/**
* 手机端端移动
* @param e event
*/
move(e){
if(!this.canMove)return
var touch;
if(e.changedTouches){
touch = e.changedTouches[0];
}else{
touch = e
}
this.$parent.canClick = false;
if(this.canChangeMode){
if(Math.abs(touch.clientX - this.moveStartX) > Math.abs(touch.clientY - this.moveStartY)){
this.moveMode = 1
}else{
this.moveMode = 2
}
this.canChangeMode = false
}
// 左右移动
if(this.moveMode == 1){
this.calendarMove.x = touch.clientX - this.moveStartX
}
// 上下移动
if(this.moveMode == 2){
if(this.calendarHeight == 100){
this.$parent.get3month()
}
let moveWidth = '';
// touch.clientY 日历动态高度
// this.moveStartY 点击位置高度坐标
moveWidth = Math.abs(touch.clientY - this.moveStartY);
if(touch.clientY > this.moveStartY && this.moveStartY< 200){
if(touch.clientY > 298){
return
}
this.calendarHeight = this.moveStartCalendarHeight + moveWidth
this.calendarMove.y = -((this.lineNum*40 > moveWidth)?this.lineNum*40 - moveWidth:0)
}else if(touch.clientY < this.moveStartY && this.moveStartY> 200){
if(touch.clientY < 100){
return
}
this.calendarHeight = this.moveStartCalendarHeight - moveWidth
this.calendarMove.y = -moveWidth
}
}
},
/**
* 手机端端结束移动
* @param e event
*/
moveEnd(e){
this.canMove = false
if(this.moveMode == 0)return
var touch;
if(e.changedTouches){
touch = e.changedTouches[0];
}else{
touch = e
}
this.canChangeMode = true
if(this.moveMode == 1){
if(this.moveStartX < touch.clientX){
if(this.moveStartX - touch.clientX < -50){
this.calendarMove.x = this.itemWidth
this.moveIndex = -1
}else{
this.calendarMove.x = 0
}
}else{
if(this.moveStartX - touch.clientX > 50){
this.calendarMove.x = -this.itemWidth
this.moveIndex = 1
}else{
this.calendarMove.x = 0
}
}
}
if(this.moveMode == 2){
if(this.moveStartY - touch.clientY < 0){
if(this.moveStartY - touch.clientY < -50){
this.moveInit(true)
this.$parent.get3month()
}else{
this.moveInit(false)
}
}else{
if(this.moveStartY - touch.clientY > 50){
this.moveInit(false)
}else{
this.moveInit(true)
this.$parent.get3month()
}
}
}
this.transition = true;
setTimeout(()=> {
this.transition = false
if(this.moveMode == 1){
this.$emit('on-change',this.moveIndex,this.isWeek)
}
},500)
},
/**
* 左右切换
* @param index 当前月索引值
*/
moveChange(index){
this.transition = false
this.calendarMove.x = 0
},
/**
* 初始化
* @param mode 类型 月或周
*/
moveInit(mode){
this.isWeek = !mode
if(mode){
var self = this
self.calendarHeight = -100
this.calendarMove.y = 0
//日历高度设置为最大高度
setTimeout(function(){
self.calendarHeight = self.$refs.calendar.offsetHeight
},300);
}else{
// 恢复高度
this.calendarHeight = 100
this.calendarMove.y = -(100*this.lineNum)
setTimeout(()=>{
this.$parent.get3week();
},150)
this.calendarMove.y = 0
}
},
/**
* 计算今天在第几行
* @param day 当天
*/
calcLineNum(day){
var year = day.getFullYear()
var month = day.getMonth()
var dt_first = new Date(year,month,1) //每个月第一天
var space = (dt_first.getDay() - 1 + 7) % 7 //月历前面空格
return parseInt((space + day.getDate() - 1) / 7)
}
}
}
</script>
<style src="@/assets/css/calendar/common.css" scoped></style>
css文件
/* 办事日历 */
.calendar-boxs{
position: relative;height: 300px; z-index: 99;}
.transition{
transition: all .2s linear;}
.calendar-body{
position: relative;}
.calendar-s-box{
height: 100%;white-space: nowrap}
.select-status{
position: absolute;top: -154px;right: 0;color: #999999;font-size: 40px;}
.calendar-box {
position: relative; background: #fff; z-index: 99; transition: all 0.2s ease;overflow: hidden;}
.calendar-box .title{
font-size: 40px;color: #333;margin-bottom: 48px;}
.calendar-head {
display: flex; height: 60px;line-height: 60px;}
.calendar-head li {
flex-grow: 1;text-align: center;color: #333;font-size: 38px;}
.calendar-today {
position: absolute;width: 100%;height: 40px;text-align: center;color: #333;z-index: 9;bottom: 40px;background: #fff;}
.calendar-toggle {
position: absolute;width: 100%;height: 20px;z-index: 9;bottom: 20px;background: #fff;}
.toggle-line {
position: absolute;left: 50%;bottom: 12px;transform: translateX(-50%);width: 30px;height: 12px;background: #d6d6d6;border-radius: 1px;}
.swiper-item {
position: absolute;width: 100%;height: 100%;top: 0;}
.swiper-item:nth-child(1) {
left: -100%;}
.swiper-item:nth-child(2) {
left: 0;}
.swiper-item:nth-child(3) {
left: 100%;}
.month ul {
display: flex;margin: 0;padding: 0;width: 100%;height: 64px;min-height: 64px;border-right: 1px solid #eee;}
.month li {
font-size: 38px;flex: 1;flex-grow: 1;color: #333;overflow: hidden;}
.week-day {
position: relative;width: 64px;height: 64px;margin: auto;text-align: center;border: 0;line-height: 64px;overflow: hidden;border-top: 1px solid #fff;z-index: 1;}
.week-day i {
display: block;text-align: center;font-style: normal;padding: 1px;line-height:64px;height:64px;}
.week-day.ischecked {
border-radius: 50px;color: #fff !important;background: #7687E9;}
.thing a {
color: #fff;background: #fff;}
.thing {
position: absolute;left: 50%;bottom: 0;transform: translateX(-50%);margin-top: 3px;color: #f5a623;}
.thing a {
cursor: pointer;display: block;width: 16px;height: 16px;word-break: break-all;line-height: 16px;color: #f5a623;background: #f5a623;border-radius: 50%;}
.othermonth {
color: #87d7e8;}
.istoday .today {
color: #fff;background: #13C2C2;border-radius: 50%;}
.thing-infos{
font-size: 40px;color: #666666;border-top: 1px solid #D8D8D8;padding-top: 40px;}
.thing-infos p{
line-height: 56px; display: flex;}
.thing-infos p span{
display: inline-block;}
.thing-infos .vertical-bar{
width: 6px;height: 40px;background: #7687E9;margin-right: 12px;}
.thing-infos .title{
color: #999999;width: 240px;text-align: right;}
.w-540{
width: 640px;}
.mb-20{
margin-bottom: 20px;}
.thing-infos>>>.van-swipe__track{
margin-bottom: 12px;}
.thing-infos>>>.van-swipe__indicators{
bottom: 0;}
.thing-infos>>>.van-swipe__indicator{
width: 12px;height: 12px;background: #d5d5d5;}
最后在页面中引入组件