yxk_h5_master/components/uni-calendar/uni-calendar.vue

765 lines
22 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<view v-if="maskShow && !insert" :class="{ 'ani-mask-show': aniMaskShow }" class="uni-calendar__mask" />
<view v-if="maskShow || insert" :class="{
'ani-calendar-show': aniMaskShow,
'uni-calendar__static': insert,
}" class="uni-calendar__box">
<view v-if="!insert" class="uni-calendar__nav">
<view class="uni-calendar__nav-item" @click="close">取消</view>
<view class="uni-calendar__nav-item" @click="confirm">确认</view>
</view>
<view class="uni-calendar__wrapper">
<view class="uni-calenda__content">
<view class="uni-calendar__panel">
<view class="uni-calendar__date-befor" @tap="dataBefor(-1, 'month')"><text
class="iconfont icon-jiantou" /></view>
<view class="uni-calendar__panel-box">
<view>{{ canlender.year }}年</view>
<view>{{ canlender.month }}月</view>
</view>
<view class="uni-calendar__date-after uni-calendar__rollback" @tap="dataBefor(1, 'month')"><text
class="iconfont icon-jiantou" /></view>
<view class="uni-calendar__backtoday" @tap="backtoday">回到今天</view>
</view>
<view v-if="isLunar" class="uni-calendar__day-detail">
<view>{{
canlender.year +
"年" +
canlender.month +
"月" +
canlender.date +
"日 " +
canlender.lunar.astro +
")"
}}</view>
<view>
{{
canlender.lunar.gzYear +
"年" +
canlender.lunar.gzMonth +
"月" +
canlender.lunar.gzDay +
"日(" +
canlender.lunar.Animal +
"年)"
}}
{{ canlender.lunar.IMonthCn + canlender.lunar.IDayCn }}
{{ canlender.lunar.isTerm ? canlender.lunar.Term : "" }}
</view>
</view>
<view class="uni-calendar__header">
<view class="uni-calendar__week">日</view>
<view class="uni-calendar__week">一</view>
<view class="uni-calendar__week">二</view>
<view class="uni-calendar__week">三</view>
<view class="uni-calendar__week">四</view>
<view class="uni-calendar__week">五</view>
<view class="uni-calendar__week"></view>
</view>
<uni-calendar-item :canlender="canlender" :lunar="isLunar" @selectDays="selectDays" />
</view>
</view>
</view>
</view>
</template>
<script>
import CALENDAR from "./calendar.js";
import uniCalendarItem from "./uni-calendar-item.vue";
export default {
name: "UniCalendar",
components: {
uniCalendarItem,
},
props: {
/**
* 当前日期
*/
date: {
type: String,
default: "",
},
/**
* 打点日期
*/
selected: {
type: Array,
default() {
return [];
},
},
/**
* 是否开启阴历日期
*/
lunar: {
type: Boolean,
default: false,
},
/**
* 是否禁用今天之前的日期
*/
disableBefore: {
type: Boolean,
default: false,
},
/**
* 开始时间
*/
startDate: {
type: String,
default: "",
},
/**
* 结束时间
*/
endDate: {
type: String,
default: "",
},
/**
* 范围
*/
range: {
type: Boolean,
default: false,
},
/**
* 插入
*/
insert: {
type: Boolean,
default: false,
},
},
data() {
/**
* TODO 兼容新旧编译器
* 新编译器(自定义组件模式)下必须使用固定数值,否则部分平台下会获取不到节点。
* 随机数值是在旧编译器下使用的,旧编译器模式已经不推荐使用,后续直接废掉随机数值的写法。
*/
return {
maskShow: false, // 显示日历
aniMaskShow: false,
dateShow: false, // 日期是否选择
canlender: {
weeks: [],
},
multiple: 0,
multipleDates: {
begin: "",
end: "",
data: [],
},
isLunar: false,
};
},
watch: {
date() {
this.init();
},
selected() {
this.init();
},
lunar(newVal) {
this.isLunar = newVal;
this.init();
},
disableBefore() {
this.init();
},
startDate() {
this.init();
},
endDate() {
this.init();
},
},
created() {
this.isLunar = this.lunar;
this.init();
},
methods: {
init() {
// 初始化日历
// this.canlender = this.getWeek(this.date || new Date());
this.getMonthAll(0, this.date, true);
},
open() {
this.maskShow = true;
this.multiple = 0;
this.multipleDates.data = [];
this.multipleDates.begin = "";
this.multipleDates.end = "";
this.init();
this.$nextTick(() => {
setTimeout(() => (this.aniMaskShow = true), 30);
});
},
close() {
this.aniMaskShow = false;
this.$nextTick(() => {
setTimeout(() => (this.maskShow = false), 300);
});
},
confirm() {
this.setEmit("confirm");
this.close();
},
/**
* 获取当前月份全部日期
*/
getMonthAll(index, date) {
if (date === "") {
date = new Date();
}
const canlender = this.getWeek(this.getDate(date, index, "month"));
this.canlender = canlender;
if (this.insert) {
this.setEmit("change");
}
},
/**
* 设置事件
* @param {Object} canlender
*/
setEmit(name) {
const canlender = this.canlender;
this.$emit(name, {
range: this.range ? this.multipleDates : {},
year: canlender.year,
month: canlender.month,
date: canlender.date,
lunar: canlender.lunar,
clockinfo: canlender.clockinfo || {},
fulldate: canlender.year + "-" + canlender.month + "-" + canlender.date,
});
},
/**
* 今天之前是否禁用
* @param {Object} year 年
* @param {Object} month 月
* @param {Object} date 日
*/
isDisableBefore(year, month, date) {
const nowDate = this.date || new Date();
const time = year + "-" + month + "-" + date;
let startDate = false;
let endDate = false;
if (this.startDate) {
startDate = this.dateCompare(this.startDate, time);
}
if (this.endDate) {
endDate = this.dateCompare(this.getDate(this.endDate, 1), time);
}
if (this.disableBefore) {
if (!this.startDate) {
if (!this.endDate) {
return !this.dateCompare(this.getDate(nowDate, 0), time);
} else {
return !this.dateCompare(this.getDate(nowDate, 0), time) || endDate;
}
} else {
return (
!this.dateCompare(this.getDate(nowDate, 0), time) ||
!startDate ||
endDate
);
}
} else {
if (!this.startDate) {
if (!this.endDate) {
return false;
} else {
return endDate;
}
} else {
return !startDate || endDate;
}
}
},
/**
* 返回今天
*/
backtoday() {
this.getMonthAll(0, this.date);
},
/**
* 切换前一月 || 后一月
* @param {Object} id
* @param {Object} types
*/
dataBefor(id, types) {
const year =
this.canlender.year +
"-" +
this.canlender.month +
"-" +
this.canlender.date;
this.getMonthAll(id, year);
},
/**
* 选择当前的日期
* week 当前的周
* index 点击的下标索引
* ischeck 是否选中
*/
selectDays(params) {
const { week, index, ischeck, isDay } = params;
if (!ischeck) return;
if (isDay) return;
// 多选判断
const canlender = this.canlender;
const month =
canlender.weeks[week][index].month < 10
? "0" + canlender.weeks[week][index].month
: canlender.weeks[week][index].month;
const date =
canlender.weeks[week][index].date < 10
? "0" + canlender.weeks[week][index].date
: canlender.weeks[week][index].date;
const time = canlender.year + "-" + month + "-" + date;
this.isClick = true;
// this.multiple = this.multiple === 0 ? 1 : 0;
if (this.multiple === 0) {
this.multipleDates.begin = time;
this.multiple = 1;
} else if (this.multiple === 1) {
this.multiple = 2;
if (this.multipleDates.data) {
this.multipleDates.data = [];
}
const compare = this.dateCompare(this.multipleDates.begin, time);
if (compare) {
this.multipleDates.data = this.geDateAll(
this.multipleDates.begin,
time
);
this.multipleDates.end = time;
} else {
this.multipleDates.data = this.geDateAll(
time,
this.multipleDates.begin
);
this.multipleDates.end = this.multipleDates.begin;
this.multipleDates.begin = time;
}
} else {
this.multiple = 0;
this.multipleDates.data = [];
this.multipleDates.begin = "";
this.multipleDates.end = "";
}
this.getMonthAll(0, time);
},
// 获取日历内容
getWeek(dateData) {
// 判断当前是 安卓还是ios ,传入不容的日期格式
if (typeof dateData !== "object") {
dateData = dateData.replace(/-/g, "/");
}
const selected = this.selected;
const nowDate = this.getDate(this.date || new Date());
const { year, month, date, day } = this.getNewDate(dateData);
let canlender = [];
let dates = {
firstDay: new Date(year, month - 1, 1).getDay(),
lastMonthDays: [], // 上个月末尾几天
currentMonthDys: [], // 本月天数
nextMonthDays: [], // 下个月开始几天
endDay: new Date(year, month, 0).getDay(),
weeks: [],
};
// 循环上个月末尾几天添加到数组
for (let i = dates.firstDay; i > 0; i--) {
const beforeDate = new Date(year, month - 1, -i + 1).getDate() + "";
dates.lastMonthDays.push({
date: beforeDate,
month: month - 1,
disable: this.isDisableBefore(year, month - 1, beforeDate),
lunar: this.getlunar(year, month - 1, beforeDate),
isDay: false,
});
}
let clockinfo = {
have: false,
};
// 循环本月天数添加到数组
for (let i = 1; i <= new Date(year, month, 0).getDate(); i++) {
let have = false;
let clockinfoTemp = {};
// 处理打卡信息
for (let j = 0; j < selected.length; j++) {
const selDate = selected[j].date.split("-");
if (
Number(year) === Number(selDate[0]) &&
Number(month) === Number(selDate[1]) &&
Number(i) === Number(selDate[2])
) {
have = true;
clockinfoTemp.have = true;
clockinfoTemp.date = selected[j].date;
if (selected[j].info) {
clockinfoTemp.info = selected[j].info;
}
if (
JSON.stringify(selected[j].data) === "{}" ||
selected[j].data !== undefined
) {
clockinfoTemp.data = selected[j].data;
}
if (
Number(year) === Number(selDate[0]) &&
Number(month) === Number(selDate[1]) &&
Number(date) === Number(selDate[2])
) {
clockinfo = clockinfoTemp;
}
}
}
// 多选
const { begin, end, data } = this.multipleDates;
const [bYear, bMonth, bDate] = begin.split("-");
const [eYear, eMonth, eDate] = end.split("-");
let checked = false;
let multipleBegin = false;
let multipleEnd = false;
data.forEach((item, index) => {
const [mYear, mMonth, mDate] = item.split("-");
if (
year === Number(mYear) &&
month === Number(mMonth) &&
i === Number(mDate)
) {
checked = true;
}
});
// 开始日期
if (
year === Number(bYear) &&
month === Number(bMonth) &&
i === Number(bDate)
) {
multipleBegin = true;
}
// 结束日期
if (
year === Number(eYear) &&
month === Number(eMonth) &&
i === Number(eDate)
) {
// console.log(eYear, eMonth, eDate, 'end');
multipleEnd = true;
}
dates.currentMonthDys.push({
checked: this.range ? checked : false,
multipleBegin: this.range ? multipleBegin : false,
multipleEnd: this.range ? multipleEnd : false,
date: i + "",
month: month,
have,
clockinfo: clockinfoTemp,
disable: this.isDisableBefore(year, month, i + ""),
lunar: this.getlunar(year, month, i + ""),
isDay:
nowDate ===
year +
"-" +
(month < 10 ? "0" + month : month) +
"-" +
(i < 10 ? "0" + i : i),
});
}
const surplus =
42 - (dates.lastMonthDays.length + dates.currentMonthDys.length);
// 循环下个月开始几天 添加到数组
for (let i = 1; i < surplus + 1; i++) {
dates.nextMonthDays.push({
date: i + "",
month: month + 1,
disable: this.isDisableBefore(year, month + 1, i + ""),
lunar: this.getlunar(year, month + 1, i + ""),
isDay: false,
});
}
canlender = canlender.concat(
dates.lastMonthDays,
dates.currentMonthDys,
dates.nextMonthDays
);
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
dates.weeks[parseInt(i / 7)] = new Array(7);
}
dates.weeks[parseInt(i / 7)][i % 7] = canlender[i];
}
return {
weeks: dates.weeks,
month: month,
date: date,
day: day,
year: year,
clockinfo,
lunar: CALENDAR.solar2lunar(year, month, date),
lastDate: dates.currentMonthDys[dates.currentMonthDys.length - 1].date,
};
},
/**
* 计算阴历日期显示
*/
getlunar(year, month, date) {
return CALENDAR.solar2lunar(year, month, date).IDayCn;
},
/**
* 获取日期
* @param {Object} dateData
*/
getNewDate(dateData) {
const _date = new Date(dateData);
return {
year: _date.getFullYear(), // 年
month: _date.getMonth() + 1, // 月
date: _date.getDate(), // 日
day: _date.getDay(), // 天
};
},
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = "day") {
if (typeof date !== "object") {
date = date.replace(/-/g, "/");
}
const dd = new Date(date);
switch (str) {
case "day":
dd.setDate(dd.getDate() + AddDayCount); // 获取AddDayCount天后的日期
break;
case "month":
dd.setMonth(dd.getMonth() + AddDayCount); // 获取AddDayCount天后的日期
break;
case "year":
dd.setFullYear(dd.getFullYear() + AddDayCount); // 获取AddDayCount天后的日期
break;
}
const y = dd.getFullYear();
const m =
dd.getMonth() + 1 < 10 ? "0" + (dd.getMonth() + 1) : dd.getMonth() + 1; // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate(); // 获取当前几号不足10补0
return y + "-" + m + "-" + d;
},
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace("-", "/").replace("-", "/"));
// 计算详细项的截止时间
endDate = new Date(endDate.replace("-", "/").replace("-", "/"));
if (startDate <= endDate) {
return true;
} else {
return false;
}
},
geDateAll(begin, end) {
var arr = [];
var ab = begin.split("-");
var ae = end.split("-");
var db = new Date();
db.setUTCFullYear(ab[0], ab[1] - 1, ab[2]);
var de = new Date();
de.setUTCFullYear(ae[0], ae[1] - 1, ae[2]);
var unixDb = db.getTime() - 24 * 60 * 60 * 1000;
var unixDe = de.getTime() - 24 * 60 * 60 * 1000;
for (var k = unixDb; k <= unixDe; ) {
// console.log((new Date(parseInt(k))).format());
k = k + 24 * 60 * 60 * 1000;
arr.push(this.getDate(new Date(parseInt(k))));
}
return arr;
},
},
};
</script>
<style>
@charset "UTF-8";
@font-face {
font-family: iconfont;
src: url(//at.alicdn.com/t/font_989023_qdgy7euvg4.eot?t=1545961121132);
src: url(//at.alicdn.com/t/font_989023_qdgy7euvg4.eot?t=1545961121132#iefix) format("embedded-opentype"),
url("data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAPcAAsAAAAABiAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8fEf5Y21hcAAAAYAAAABLAAABcOcutbxnbHlmAAABzAAAACgAAAAoOZ2GtGhlYWQAAAH0AAAALwAAADYTtoNAaGhlYQAAAiQAAAAcAAAAJAfeA4NobXR4AAACQAAAAAgAAAAICAAAAGxvY2EAAAJIAAAABgAAAAYAFAAAbWF4cAAAAlAAAAAeAAAAIAENABJuYW1lAAACcAAAAUUAAAJtPlT+fXBvc3QAAAO4AAAAIQAAADLf6deseJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByesT1jY27438AQw9zI0AAUZgTJAQDeIAvweJxjYGBgZWBgYAZiHSBmYWBgDGFgZAABP6AoI1icmYELLM7CoARWwwISf8b2/z+MBPJZwCQDIxvDKOABkzJQHjisIJiBEQA3lgmBAAABAAD/gAMAA4EABQAACQE1CQE1AQACAP6IAXgBgP4AiAF4AXiIAAB4nGNgZGBgAOLdZzma4vltvjJwszCAwA3v+QsR9P8GFgbmRiCXg4EJJAoAMzgKmgB4nGNgZGBgbvjfwBDDwgACQJKRARUwAQBHCAJrBAAAAAQAAAAAAAAAABQAAHicY2BkYGBgYmBjANEgFgMDFxAyMPwH8xkACS0BIAAAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAiZGJkZmBIyszMa8kv9SEgQEAGD0DTAAAAA==") format("woff"),
url(//at.alicdn.com/t/font_989023_qdgy7euvg4.ttf?t=1545961121132) format("truetype"),
url(//at.alicdn.com/t/font_989023_qdgy7euvg4.svg?t=1545961121132#iconfont) format("svg");
}
.iconfont {
font-family: iconfont !important;
font-size: 32upx;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-jiantou:before {
content: "\e606";
}
.uni-calendar__mask {
position: fixed;
bottom: 0;
top: 0;
width: 100%;
background: rgba(0, 0, 0, 0.4);
transition: all 0.3s;
opacity: 0;
z-index: 998;
}
.uni-calendar__mask.ani-mask-show {
opacity: 1;
}
.header {
display: flex;
justify-content: center;
align-items: center;
position: relative;
height: 100upx;
background: #fff;
z-index: 999;
font-size: 32upx;
}
.uni-calendar__box {
position: fixed;
bottom: 0;
z-index: 999;
width: 100%;
box-sizing: border-box;
transition: all 0.3s;
transform: translateY(100%);
}
.uni-calendar__box.ani-calendar-show {
transform: translateY(0);
}
.uni-calendar__box.uni-calendar__static {
position: static;
transform: translateY(0);
}
.uni-calendar__box .uni-calendar__nav {
display: flex;
justify-content: space-between;
height: 100upx;
border-bottom: 1px #f5f5f5 solid;
background: #f5f5f5;
padding: 0 10upx;
}
.uni-calendar__box .uni-calendar__nav .uni-calendar__nav-item {
display: flex;
justify-content: center;
align-items: center;
width: 100upx;
height: 100upx;
color: #333;
}
.uni-calendar__wrapper {
width: 100%;
box-sizing: border-box;
font-size: 26rpx;
background: #fff;
transition: all 0.3s;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel {
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
height: 100rpx;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel .uni-calendar__date-after,
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel .uni-calendar__date-befor {
display: flex;
justify-content: center;
align-items: center;
height: 80rpx;
width: 80rpx;
text-align: center;
line-height: 80rpx;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel .uni-calendar__date-after.uni-calendar__rollback,
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel .uni-calendar__date-befor.uni-calendar__rollback {
transform: rotate(180deg);
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel .uni-calendar__panel-box {
display: flex;
justify-content: center;
align-items: center;
width: 200upx;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__panel .uni-calendar__backtoday {
position: absolute;
right: 0;
top: 25rpx;
padding: 0 10rpx;
padding-left: 20rpx;
height: 50rpx;
line-height: 50rpx;
border: 1px rgba(253, 46, 50, 0.5) solid;
border-right: none;
font-size: 24rpx;
border-top-left-radius: 50rpx;
border-bottom-left-radius: 50rpx;
color: rgba(253, 46, 50, 0.7);
background: rgba(241, 233, 233, 0.4);
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__day-detail {
padding: 20upx;
padding-left: 30upx;
border-top: 1px #f5f5f5 solid;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__header {
display: flex;
font-size: 28upx;
border-top: 1px #f5f5f5 solid;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__header .uni-calendar__week {
width: 100%;
text-align: center;
line-height: 80rpx;
color: #333;
font-weight: 700;
}
.uni-calendar__wrapper .uni-calenda__content .uni-calendar__body {
display: flex;
flex-wrap: wrap;
font-size: 28upx;
}
</style>