Files
2025-09-28 19:15:37 +08:00

178 lines
6.2 KiB
TypeScript
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.
// pages/checkin/checkin.ts
interface CalendarDay {
day: number | string; // 日期数字或空字符串
fullDate?: string; // 完整日期字符串,如 'YYYY-MM-DD'
isPrevMonth?: boolean; // 是否上月日期
isNextMonth?: boolean; // 是否下月日期
isToday?: boolean; // 是否今天
isCheckedIn?: boolean; // 是否已签到
}
Page({
data: {
weekdays: ['日', '一', '二', '三', '四', '五', '六'],
currentYear: 0,
currentMonth: 0, // 1-12月
calendarDays: [] as CalendarDay[], // 日历日期数据
consecutiveCheckInDays: 0, // 连续签到天数
monthCheckInDays: 0, // 本月签到天数
todayCheckedIn: false, // 今日是否已签到
// 假设这些是用户已签到的日期(仅日期数字),在真实项目中从后端获取
checkedInDates: [] as number[], // [1, 5, 18, 29] 表示当月哪些天已签到
// 用于保存当前显示的月份的Date对象方便计算
displayMonthDate: new Date(),
},
onLoad() {
this.initCalendar();
this.fetchCheckInStats(); // 模拟从后端获取签到数据
},
/**
* 初始化日历,生成当前月份的日期
*/
initCalendar() {
const today = new Date();
this.data.displayMonthDate = new Date(today.getFullYear(), today.getMonth(), 1); // 设置为当前月的第一天
this.renderCalendar(this.data.displayMonthDate);
},
/**
* 渲染指定月份的日历
* @param date 当前月份的任意一天,例如 new Date(2025, 8, 1) 表示 2025年9月
*/
renderCalendar(date: Date) {
const year = date.getFullYear();
const month = date.getMonth(); // 0-11
this.setData({
currentYear: year,
currentMonth: month + 1, // 显示给用户是1-12月
});
const calendarDays: CalendarDay[] = [];
const firstDayOfMonth = new Date(year, month, 1);
const lastDayOfMonth = new Date(year, month + 1, 0); // 当月最后一天
// 补充上个月的日期(如果需要)
const startDayOfWeek = firstDayOfMonth.getDay(); // 0-60是周日
for (let i = 0; i < startDayOfWeek; i++) {
calendarDays.push({ day: '', isPrevMonth: true }); // 用空字符串占位或显示上月日期
}
// 填充当前月份的日期
for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
const currentDay = new Date(year, month, i);
const isToday = this.isSameDay(currentDay, new Date());
const isCheckedIn = this.data.checkedInDates.includes(i); // 判断是否已签到
calendarDays.push({
day: i,
fullDate: this.formatDate(currentDay),
isToday: isToday,
isCheckedIn: isCheckedIn,
});
}
// 补充下个月的日期如果需要凑够6行或7的倍数
const totalDays = calendarDays.length;
const remainingDays = 42 - totalDays; // 假设日历固定6行7列共42个格子
for (let i = 0; i < remainingDays; i++) {
calendarDays.push({ day: '', isNextMonth: true }); // 用空字符串占位
}
this.setData({
calendarDays: calendarDays,
});
},
/**
* 模拟从后端获取签到统计数据和已签到日期
*/
fetchCheckInStats() {
// 真实项目中这里会发起 wx.request 到您的后端接口
// 假设后端返回的数据格式如下:
const mockApiResponse = {
consecutiveCheckInDays: 29, // 连续签到天数
monthCheckInDays: 15, // 本月签到天数
todayCheckedIn: false, // 假设今天未签到
checkedInDaysInMonth: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 29], // 当月已签到的日期数字
};
this.setData({
consecutiveCheckInDays: mockApiResponse.consecutiveCheckInDays,
monthCheckInDays: mockApiResponse.monthCheckInDays,
todayCheckedIn: mockApiResponse.todayCheckedIn,
checkedInDates: mockApiResponse.checkedInDaysInMonth,
});
// 重新渲染日历以应用新的签到状态
this.renderCalendar(this.data.displayMonthDate);
},
/**
* 处理签到按钮点击
*/
handleCheckIn() {
if (this.data.todayCheckedIn) {
wx.showToast({ title: '今日已签到', icon: 'none' });
return;
}
// 模拟后端签到逻辑
wx.showLoading({ title: '签到中...' });
setTimeout(() => {
// 假设后端返回签到成功
const today = new Date().getDate();
const newCheckedInDates = [...this.data.checkedInDates, today];
this.setData({
todayCheckedIn: true,
consecutiveCheckInDays: this.data.consecutiveCheckInDays + 1, // 假设连续+1
monthCheckInDays: this.data.monthCheckInDays + 1, // 假设当月+1
checkedInDates: newCheckedInDates,
});
// 重新渲染日历,标记今天为已签到
this.renderCalendar(this.data.displayMonthDate);
wx.hideLoading();
wx.showToast({ title: '签到成功!', icon: 'success' });
}, 1000); // 模拟网络请求
},
/**
* 处理日历中的日期点击(可选,如果需要点击日期查看历史签到等)
*/
handleDayClick(event: WechatMiniprogram.TouchEvent) {
const fullDate = event.currentTarget.dataset.date;
if (fullDate) {
console.log('点击了日期:', fullDate);
// 可在此处实现点击日期查看历史签到详情等逻辑
}
},
/**
* 辅助函数:判断两个日期是否是同一天 (忽略时间)
*/
isSameDay(date1: Date, date2: Date): boolean {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
},
/**
* 辅助函数:格式化日期为 YYYY-MM-DD
*/
formatDate(date: Date): string {
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
},
});