perf: 优化签到数据

This commit is contained in:
kuaifan 2023-03-04 10:21:48 +08:00
parent 0a84a8718e
commit b5059c13a3
3 changed files with 112 additions and 210 deletions

View File

@ -1513,6 +1513,7 @@ class UsersController extends AbstractController
* @apiName checkin__list * @apiName checkin__list
* *
* @apiParam {String} ym -2020-01 * @apiParam {String} ym -2020-01
* @apiParam {Number} [before] 取月份之前的数据单位月数最大3
* *
* @apiSuccess {Number} ret 返回状态码1正确、0错误 * @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {String} msg 返回信息(错误描述)
@ -1526,6 +1527,11 @@ class UsersController extends AbstractController
$start = Carbon::parse(date("Y-m-01 00:00:00", strtotime($ym))); $start = Carbon::parse(date("Y-m-01 00:00:00", strtotime($ym)));
$end = (clone $start)->addMonth()->subSecond(); $end = (clone $start)->addMonth()->subSecond();
// //
$before = min(3, intval(Request::input('before')));
if ($before > 0) {
$start = $start->subMonths($before);
}
//
$recordTimes = UserCheckinRecord::getTimes($user->userid, [$start, $end]); $recordTimes = UserCheckinRecord::getTimes($user->userid, [$start, $end]);
$array = []; $array = [];
$startT = $start->timestamp; $startT = $start->timestamp;

View File

@ -8,7 +8,7 @@
</div> </div>
<Button v-if="hasNextMonth" class="calendar-header-back" size="small" @click="nowMonth">{{$L('返回本月')}}</Button> <Button v-if="hasNextMonth" class="calendar-header-back" size="small" @click="nowMonth">{{$L('返回本月')}}</Button>
</div> </div>
<table class="sign_tab" border="0px" cellpadding="0px" cellspacing="0px"> <table class="check-table">
<thead> <thead>
<tr> <tr>
<th>{{$L('日')}}</th> <th>{{$L('日')}}</th>
@ -21,32 +21,25 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="item in dateArr" v-if="contains(item)"> <tr v-for="item in dateArray">
<template v-for="data in item"> <template v-for="data in item">
<td v-if="isCheck(data.date)" <td v-if="data.month" :class="{today: data.today, checkin:isCheck(data.date)}">
:class="{'disa':monthClass(data.month), 'cur_day': doCheck(data.date),'check_day': isCheck(data.date) }"> <ETooltip max-width="auto" :disabled="!isCheck(data.date)">
<Tooltip max-width="auto" transfer>
<div slot="content" v-html="getTimes(data.date)"></div> <div slot="content" v-html="getTimes(data.date)"></div>
<template v-if="doCheck(data.date)">{{$L('今天')}}</template> <div class="item-day">
<template v-else>{{data.date | getCD}}</template> <div v-if="data.today">{{$L('今天')}}</div>
<span :class="{'ui-state-down': true }">{{$L('已签到')}}</span> <div v-else>{{data.day}}</div>
</Tooltip>
<div v-if="isCheck(data.date)" class="ui-state-down">{{$L('已签到')}}</div>
<span v-else-if="data.today" class="ui-state-default">{{$L('尚未签到')}}</span>
</div>
</ETooltip>
</td> </td>
<template v-if="(!isCheck(data.date) && (doCheck(data.date) && !hasCheckin))"> <td v-else class="disabled">
<td v-if="!monthClass(data.month)" <div class="item-day">
@click="checkNow" <div>{{data.day}}</div>
:class="{'disa':monthClass(data.month), 'over':data.date == '', 'cur_day': doCheck(data.date) }"> <div v-if="isCheck(data.date)" class="ui-state-down">{{$L('已签到')}}</div>
{{$L('今天')}} </div>
<span :class="{'ui-state-default': true }">{{$L('尚未签到')}}</span>
</td>
<td v-else
:class="{'disa':monthClass(data.month), 'over':data.date == '', 'cur_day': doCheck(data.date) }">
{{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) }">
{{data.date | getCD}}
</td> </td>
</template> </template>
</tr> </tr>
@ -71,135 +64,85 @@ export default {
}, },
data() { data() {
return { return {
today: new Date(),
year: '', year: '',
month: '', month: '',
day: '',
date: '',
startTime: '', startTime: '',
endTime: '', endTime: '',
dateArr: [],
hasCheckin: false, dateArray: [],
historys: [],
}; };
}, },
created() { created() {
this.year = this.today.getFullYear(); const today = new Date()
this.month = this.today.getMonth() + 1; this.year = today.getFullYear();
this.day = this.today.getDay(); this.month = today.getMonth() + 1;
this.date = this.today.getDate();
this.getCalendar(); this.generateCalendar();
},
filters: {
getCD(val) {
return val.split('/')[2]
}
}, },
watch: { watch: {
dateArr: { checkin: {
deep: true, handler(arr) {
handler: function (val, oldVal) { arr.some(({date, section}) => {
this.startTime = val[0][0].date; date = date.replace(/-0?/g, '/')
this.endTime = val[5][6].date; let index = this.historys.findIndex(item => item.date == date)
this.setMonth(this.year + '/' + this.month, [this.startTime, this.endTime]); if (index > -1) {
this.historys.splice(index, 1, {date, section})
} else {
this.historys.push({date, section})
} }
})
},
immediate: true
} }
}, },
computed: { computed: {
hasNextMonth() { hasNextMonth() {
const {year, month} = this; const {year, month} = this;
const {y, m} = {y: $A.formatDate("Y"), m: $A.formatDate("m")}; return parseInt(year) != $A.formatDate("Y") || parseInt(month) < $A.formatDate("m");
return parseInt(year) != y || parseInt(month) < parseInt(m);
} }
}, },
methods: { methods: {
checkNow() { ym() {
this.$emit('checkIn') return this.year + '-' + (this.month < 10 ? ('0' + this.month) : this.month);
}, },
setMonth(date,) { isCheck(date) {
return !!this.historys.find(item => item.date == date)
},
setMonth(date) {
this.$emit('setMonth', date, [this.startTime, this.endTime]) this.$emit('setMonth', date, [this.startTime, this.endTime])
}, },
monthClass(type) { getTimes(date) {
return type != 'cur'; const data = this.historys.find(item => item.date == date)
}, return data?.section.map(item => {
getTimes(thisDay) {
for (let i in this.checkin) {
if (this.checkin.hasOwnProperty(i)) {
if (new Date(thisDay).getTime() == $A.Date(this.checkin[i].date).getTime()) {
return this.checkin[i].section.map(item => {
return `${item[0]} - ${item[1] || 'None'}` return `${item[0]} - ${item[1] || 'None'}`
}).join('<br/>'); }).join('<br/>')
}
}
}
}, },
isLeap() { generateCalendar() {
const year = this.year; let today = new Date($A.formatDate("Y/m/d"))
if (year % 4 == 0 && year % 100 > 0) { let one = new Date(this.year, this.month - 1, 1)
return true; let calcTime = one.getTime() - one.getDay() * 86400 * 1000
} else return year % 400 == 0 && year % 3200 > 0; let array = []
},
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;
},
getCalendar() {
let len = this.getLen();
let d = new Date(this.year, this.month - 1, 1);
let dfw = d.getDay();
let arr = [];
let tem = 0;
let nextTem = 1;
let pre = dfw - 1
let _lastLen = this.getLen(this.month - 1)
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
arr[i] = []; array[i] = []
for (let j = 0; j < 7; j++) { for (let j = 0; j < 7; j++) {
tem++; let curDate = new Date(calcTime)
if (tem - dfw > 0 && tem - dfw <= len) { let curMonth = curDate.getMonth() + 1
arr[i][j] = {date: this.year + '/' + (this.month) + '/' + (tem - dfw), month: 'cur'}; array[i][j] = {
} else { day: curDate.getDate(),
if (tem <= dfw) { date: `${curDate.getFullYear()}/${curMonth}/${curDate.getDate()}`,
arr[i][j] = { today: today.getTime() == curDate.getTime(),
date: this.year + '/' + (this.month - 1) + '/' + (_lastLen - pre), future: today.getTime() < curDate.getTime(),
month: 'pre' month: curMonth == this.month
}; }
pre--; calcTime += 86400 * 1000
} else {
arr[i][j] = {date: this.year + '/' + (this.month + 1) + '/' + (nextTem), month: 'next'};
nextTem++
} }
} }
} this.dateArray = array
} this.startTime = array[0][0].date;
this.dateArr = arr; this.endTime = array[5][6].date;
this.setMonth(this.year + '/' + this.month, [this.startTime, this.endTime]);
}, },
nextMonth() { nextMonth() {
if (this.month == 12) { if (this.month == 12) {
@ -208,7 +151,7 @@ export default {
} else { } else {
this.month++; this.month++;
} }
this.getCalendar(); this.generateCalendar();
this.$emit('changeMonth', this.ym()) this.$emit('changeMonth', this.ym())
}, },
prevMonth() { prevMonth() {
@ -218,39 +161,14 @@ export default {
} else { } else {
this.month--; this.month--;
} }
this.getCalendar(); this.generateCalendar();
this.$emit('changeMonth', this.ym()) this.$emit('changeMonth', this.ym())
}, },
nowMonth() { nowMonth() {
this.year = parseInt($A.formatDate("Y")); this.year = parseInt($A.formatDate("Y"));
this.month = parseInt($A.formatDate("m")); this.month = parseInt($A.formatDate("m"));
this.getCalendar(); this.generateCalendar();
this.$emit('changeMonth', this.ym()) this.$emit('changeMonth', this.ym())
},
contains(arr) {
return !((arr[0] == '') && (arr[1] == '') && (arr[2] == '') && (arr[3] == '') && (arr[4] == '') && (arr[5] == '') && (arr[6] == ''));
},
isCheck(index) {
const todayDate = new Date();
for (let i in this.checkin) {
if ($A.Date(todayDate.getFullYear() + '/' + todayDate.getMonth() + '/' + todayDate.getDate()).getTime() == $A.Date(this.checkin[i].date).getTime()) {
//
this.hasCheckin = true;
}
if (new Date(index).getTime() == $A.Date(this.checkin[i].date).getTime()) {
//console.log('')
return true;
}
}
return false;
},
doCheck(d) {
let dString = new Date().getFullYear() + '/' + (new Date().getMonth() + 1) + '/' + new Date().getDate();
return new Date(d).getTime() == new Date(dString).getTime();
},
ym() {
return this.year + '-' + (this.month < 10 ? ('0' + this.month) : this.month);
} }
} }
}; };
@ -308,8 +226,11 @@ export default {
right: 10px; right: 10px;
} }
} }
.sign_tab { .check-table {
width: 100%; width: 100%;
border: 0;
border-spacing: 0;
border-collapse: collapse;
table-layout: fixed; table-layout: fixed;
th { th {
text-align: center; text-align: center;
@ -318,48 +239,38 @@ export default {
} }
td { td {
position: relative; position: relative;
padding: 15px 0;
text-align: center; text-align: center;
font-size: 14px;
border-right: 1px solid #eee; border-right: 1px solid #eee;
border-top: 1px solid #eee; border-top: 1px solid #eee;
font-size: 14px;
height: 52px;
.item-day {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
line-height: 20px;
}
&:last-child { &:last-child {
border-right: 0; border-right: 0;
} }
&.over { &.disabled {
background-color: #fff; color: #ccc;
border-left: 0; background: none;
border-right: 0;
}
&.disa {
color: #ccc !important;
background: none !important;
* { * {
color: #ccc !important; color: #ccc;
} }
} }
&.check_day { &.today {
background-color: #f8f8f8; background-color: #F29D38;
color: #58ce7a; color: #FFF;
position: relative;
font-size: 14px;
padding-top: 2px; padding-top: 2px;
line-height: 26px; line-height: 26px;
.ivu-tooltip {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
.ivu-tooltip-rel {
width: 100%;
height: 100%;
line-height: 26px;
padding-top: 4px;
}
} }
&.checkin {
color: #58ce7a;
background-color: #f8f8f8;
position: relative;
} }
} }
} }
@ -367,25 +278,9 @@ export default {
.ui-state-down, .ui-state-down,
.ui-state-default { .ui-state-default {
font-size: 12px; font-size: 12px;
width: 100%;
text-align: center;
position: absolute;
bottom: 3px;
left: 0;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.sign_tab {
td {
&.cur_day {
background-color: #F29D38;
color: #FFF;
padding-top: 2px;
line-height: 26px;
}
}
}
} }
</style> </style>

View File

@ -162,7 +162,8 @@ export default {
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'users/checkin/list', url: 'users/checkin/list',
data: { data: {
ym: $A.formatDate("Y-m") ym: $A.formatDate("Y-m"),
before: 1
} }
}).then(({data}) => { }).then(({data}) => {
this.latelyFormat(data) this.latelyFormat(data)
@ -173,15 +174,12 @@ export default {
latelyFormat(data) { latelyFormat(data) {
const time = $A.Time(); const time = $A.Time();
const Ym = $A.formatDate("Ym", time)
this.latelyData = []; this.latelyData = [];
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
if (Ym == $A.formatDate("Ym", time - i * 86400)) {
const ymd = $A.formatDate("Y-m-d", time - i * 86400) const ymd = $A.formatDate("Y-m-d", time - i * 86400)
const item = data.find(({date}) => date == ymd) || {date: ymd, section: []} const item = data.find(({date}) => date == ymd) || {date: ymd, section: []}
this.latelyData.push(item) this.latelyData.push(item)
} }
}
}, },
latelySection(section) { latelySection(section) {
@ -196,7 +194,10 @@ export default {
}, 600) }, 600)
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'users/checkin/list', url: 'users/checkin/list',
data: {ym} data: {
ym,
before: 1
}
}).then(({data}) => { }).then(({data}) => {
if (this.$refs.calendar.ym() != ym) { if (this.$refs.calendar.ym() != ym) {
return; return;