vue写好的组件,直接安装npm install vue-checkin --save,github地址 GitHub - hasbug/vue-checkin
或者自己写,如下
新建vue-checkin.vue,里面写
<template>
<div class="content-page uk-body">
<div class="calendar">
<button class="month-less" @click="prevMonth"> < </button>
<h4>{{year}}年{{month}}月</h4>
<button class="month-add" @click="nextMonth"> > </button>
<table class="sign_tab" border="0px" cellpadding="0px" cellspacing="0px">
<thead>
<tr>
<th>日</th>
<th>一</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in dateArr" :key="index">
<template v-if="contains(item)">
<template v-for="(data,index) in item">
<!-- 6行7列的每个单元格的date是否在签到数组里 -->
<td :class="{'disa':monthClass(data.month), 'cur_day': doCheck(data.date),'check_day': isCheck(data.date) }" v-if="isCheck(data.date)" :key="index">
<!--<span :class="{'ui-state-up': true }">已签到</span>-->
<template v-if="doCheck(data.date)">
今天
</template>
<template v-else>
{{data.date | getCD}}
</template>
<span :class="{'ui-state-down': true }">金币+{{getGold(data.date)}}</span>
</td>
<!-- 如果不在签到数组里,是今天,没签到 -->
<template v-if="(!isCheck(data.date) && (doCheck(data.date) && !hasCheckin))">
<!-- 是否是当月,如果是当月显示今天,如果不是当月显示日期 -->
<td v-if="!monthClass(data.month)" @click="checkNow" :class="{'disa':monthClass(data.month), 'over':data.date == '', 'cur_day': doCheck(data.date) }" :key="index">
今天
<span :class="{'ui-state-default': true }">点击签到</span>
</td>
<td v-else :class="{'disa':monthClass(data.month), 'over':data.date == '', 'cur_day': doCheck(data.date) }" :key="index">
{{data.date | getCD}}
</td>
</template>
<!-- 没签到,不是今天,显示日期 -->
<td v-if="!isCheck(data.date) && (!doCheck(data.date)) " :class="{'disa':monthClass(data.month), 'over':data.date == '', 'cur_day': doCheck(data.date) }" :key="index">
{{data.date | getCD}}
</td>
</template>
</template>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
export default {
name:'vueCheckin',
data() {
return {
today : new Date(),
year : '',
month : '',
day : '',
date : '',
startTime:'',
endTime:'',
dateArr: [],//6行7列的年月日和是否是当月的数据
hasCheckin:false,
};
},
props:['checkin'],
created() {
this.year = this.today.getFullYear();
this.month = this.today.getMonth() + 1;
this.day = this.today.getDay();
this.date = this.today.getDate();
this.getCalendar();
console.log(this.checkin)
},
filters: {
getCD (val){
return val.split('/')[2]
}
},
// computed:{
// con() {
// return this.
// }
// },
watch: {
dateArr: {
deep: true,
handler: function (val) {
console.log(val)
this.startTime = val[0][0].date;
this.endTime = val[5][6].date;
this.setMonth(this.year+'/'+this.month,[this.startTime, this.endTime]);
}
}
},
methods: {
//签到
checkNow() {
this.$emit('checkIn')
},
setMonth (date,){
this.$emit('setMonth',date,[this.startTime, this.endTime])
},
monthClass(type) {
if(type!='cur'){
return true
}else{
return false
}
},
getGold (thisDay) {
for(let i in this.checkin) {
var d=new Date(this.checkin[i].time.replace(/-/g, '/'));
var _ymd = d.getFullYear()+'/'+(d.getMonth()+1)+'/'+d.getDate();
if(new Date(thisDay).getTime() == new Date(_ymd).getTime()) {
return this.checkin[i].amount;
}
}
},
//是否是闰年
isLeap() {
const year = this.year;
if(year % 4 == 0 && year % 100 > 0) {
return true;
}else if(year % 400 == 0 && year % 3200 > 0) {
return true;
}else {
return false;
}
},
//单个月的天数
getLen(m) {
const month = m || this.month;
if(month == 2) {
if(this.isLeap) {
return 29;
}else {
return 28;
}
}else {
if(month < 8) {
if(month % 2 > 0) {
return 31;
}else {
return 30;
}
}else {
if(month % 2 > 0) {
return 30;
}else {
return 31;
}
}
}
},
//格式化年月日
getCalendarTime() {
return this.year + '-' + this.month + '-' + this.date;
},
//得到6行7列的每个单元格的年月日和当月前一个月后一个月
getCalendar() {
var len = this.getLen();
var d = new Date(this.year, this.month - 1, 1);
var dfw = d.getDay();
var arr = new Array();
var tem = 0;
var nextTem=1;
var pre=dfw-1
var _lastLen=this.getLen(this.month-1)
for (var i = 0; i < 6; i++) {
arr[i] = new Array();
for (var j = 0; j < 7; j++) {
tem++;
if (tem - dfw > 0 && tem - dfw <= len) {
arr[i][j] = {date:this.year+'/'+(this.month)+'/'+(tem - dfw),month:'cur'};
} else {
if(tem <= dfw){
arr[i][j] = {date:this.year+'/'+(this.month-1)+'/'+(_lastLen-pre), month:'pre'};
pre--;
}else{
arr[i][j] ={date: this.year+'/'+(this.month+1)+'/'+(nextTem), month: 'next'};
nextTem++
}
}
}
}
this.dateArr = arr;
// console.log(this.dateArr);
},
nextMonth() {
if(this.month == 12) {
this.year ++;
this.month = 1;
}else {
this.month ++;
}
this.getCalendar();
},
prevMonth() {
if(this.month == 1) {
this.year --;
this.month = 12;
}else {
this.month --;
}
this.getCalendar();
},
//如果dataArr的某一个单元格里没有数据
contains(arr) {
if((arr[0] == '') && (arr[1] == '') && (arr[2] == '') && (arr[3] == '') && (arr[4] == '') && (arr[5] == '') && (arr[6] == '')) {
return false;
}else {
return true;
}
},
//是否已签到
isCheck(index) {
for(let i in this.checkin) {
var todayDate=new Date();
var today = todayDate.getFullYear()+'/'+(todayDate.getMonth()+1)+'/'+todayDate.getDate();
var d=new Date(this.checkin[i].time.replace(/-/g, '/'));
var _ymd = d.getFullYear()+'/'+(d.getMonth()+1)+'/'+d.getDate();
if(new Date(today).getTime()==new Date(_ymd).getTime()){
//今日已经签到
this.hasCheckin = true;
}
if(new Date(index).getTime() == new Date(_ymd).getTime()) {
// console.log('已经签到')
return true;
}
}
return false;
},
//是否是今天
doCheck (d){
var dString= new Date().getFullYear()+'/'+(new Date().getMonth()+1)+'/'+new Date().getDate();
if(new Date(d).getTime() == new Date(dString).getTime()){
return true;
}
return false;
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss">
.calendar{width:100%;margin:0px 0px 20px 0px;color:#555;position: relative;}
.calendar h4 {
line-height: 40px;
background-color: #fff;
text-align: center;
color: #333;
box-shadow: 0 0 4px #bbb;
-webkit-box-shadow: 0 0 4px #bbb;
}
.calendar button {
position: absolute;
width: 30px;
height: 30px;
top: 5px;
color:#777;
background: #f3f3f3;
border: none;
}
.calendar button:focus { border: none;outline: none; }
.calendar button.month-less {left: 10px;}
.calendar button.month-add {right: 10px;}
.calendar .sign_tab{width: 100%;border-collapse: collapse;border: 1px solid #e8e8e8;border-top: 0;table-layout: fixed;}
.calendar .sign_tab th{text-align: center;height: 14.28571428571429vw;font-weight: 700;}
.calendar .sign_tab td{position: relative; border: 1px solid #eee;padding: 15px 0;text-align: center;font-size: 14px;font-family: arial;}
.calendar .sign_tab td.over{background-color: #fff;border-left: 0;border-right: 0;}
.calendar .sign_tab td.disa{
color:#ccc !important;
background: none !important;
*{
color:#ccc !important;
}
}
.calendar .sign_tab td.check_day{
background-color: #f8f8f8;
color: #58ce7a;
position: relative;
}
.calendar{
.ui-state-down,
.ui-state-default{
font-size:10px;
width: 100%;
text-align: center;
position: absolute;
bottom: 3px;
left: 0;
}
.ui-state-down{
color: #f60;
}
}
.calendar .ui-state-up{
font-size:10px;
width: 100%;
text-align: center;
position: absolute;
top: 3px;
left: 0;
}
.calendar .sign_tab td.cur_day{background-color: #FFD2D2;color: #FFF;}
.checkin-btn{
display: block;
width:90%;
margin:0 auto;
text-align: center;
font-size: 10px;
}
.tdbox{
display:flex;
}
</style>
在引用页面rili.vue,写
<template>
<div>
<vue-checkin :checkin="checkInData" @checkIn="checkIn" @setMonth="getCheckInData"></vue-checkin>
</div>
</template>
<script>
import vueCheckin from '../../components/vue-checkin.vue'
export default {
name: 'Lianxi6Rili',
components: {
vueCheckin
},
data() {
return {
checkInData:[
{
"time": "2022-11-12 08:52", //日期可以直接用2018/01/12 08:52这种正规格式,避免ios解析【-】分割的出问题
"amount": 3 //所得金币
},
{
"time": "2022-10-07 08:52",
"amount": 10
},
{
"time": "2022-11-06 08:46",
"amount": 6
},
{
"time": "2022-11-05 09:51",
"amount": 3
}
]
};
},
mounted() {
},
methods: {
checkIn() {
},
getCheckInData() {
}
},
};
</script>
<style lang="scss" scoped>
</style>
大体流程是
遍历6,得到6行,遍历7,得到7列,得到当月1号是星期几,减1就是上月的在当月显示天数,事先得到每个月的天数,计数器tem每次遍历加1,如果tem<上月的在当月显示的天数,就是上个月,得到上个月的天数,当月表格的第一天是上个月的天数-(上月的在当月显示的天数-tem-1),同理得到下个月在当月显示的天数与日期。
点击签到,向后端发送现在的年月日,出现在从后端取得的已签到数组中,遍历已签到数组,看当前月的遍历的单元的毫秒数与已签到数组的哪一项的日期的毫秒数相同,已签到