HarmonyOS 鸿蒙Next中如何实现连续打卡天数统计?
HarmonyOS 鸿蒙Next中如何实现连续打卡天数统计? 学习应用需要统计用户连续学习天数,激励用户保持学习习惯。
3 回复
原理解析
连续打卡统计需要:
- 记录每天的打卡日期
- 从最近一次打卡开始,向前检查是否连续
- 处理时区问题,使用本地日期
解决步骤
步骤1:获取本地日期字符串
function getLocalDateString(date?: Date): string {
const d = date || new Date();
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}
步骤2:计算连续打卡天数
export async function getStreakDays(): Promise<number> {
const records = await getCheckInRecords();
if (records.length === 0) return 0;
// 按日期排序(降序,最新的在前)
const sorted = records.sort((a, b) => b.date.localeCompare(a.date));
// 获取今天和昨天的日期字符串
const now = new Date();
const todayStr = getLocalDateString(now);
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
const yesterdayStr = getLocalDateString(yesterday);
// 检查最近一次打卡是今天还是昨天
const latestRecord = sorted[0];
if (latestRecord.date !== todayStr && latestRecord.date !== yesterdayStr) {
return 0; // 连续中断
}
// 从最近的打卡日期开始计算连续天数
let streak = 0;
let expectedDate = new Date(latestRecord.date + 'T00:00:00');
for (let i = 0; i < sorted.length; i++) {
const recordDate = sorted[i].date;
const expectedDateStr = getLocalDateString(expectedDate);
if (recordDate === expectedDateStr) {
streak++;
// 期望日期往前推一天
expectedDate.setDate(expectedDate.getDate() - 1);
} else if (recordDate < expectedDateStr) {
// 有断档,停止计算
break;
}
// 如果 recordDate > expectedDateStr,说明有重复记录,跳过
}
return streak;
}
步骤3:自动打卡(浏览内容时触发)
async function autoCheckIn(): Promise<void> {
const today = getLocalDateString();
const records = await getCheckInRecords();
const todayRecord = records.find(r => r.date === today);
if (!todayRecord) {
// 今天还没打卡,自动记录
await saveCheckInRecord(today);
}
}
// 在浏览内容时调用
export async function recordBrowse(contentId: string, contentType: string): Promise<boolean> {
// ... 保存浏览记录
await autoCheckIn(); // 自动打卡
return true;
}
效果图
用户学习 → 自动打卡 → 首页显示"连续学习 X 天" → 激励用户保持习惯
更多关于HarmonyOS 鸿蒙Next中如何实现连续打卡天数统计?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,可通过@State装饰器定义打卡状态变量,使用PersistentStorage持久化存储每日打卡记录。通过日期计算函数判断连续打卡,例如比较最后打卡日期与当前日期。
在HarmonyOS Next中实现连续打卡天数统计,核心在于持久化存储、日期逻辑判断和状态更新。以下是基于ArkTS的关键实现思路和代码示例:
1. 数据存储
使用轻量级数据存储Preferences保存关键数据:
- 上次打卡日期 (
lastDate) - 连续打卡天数 (
currentStreak)
import { preferences } from '@kit.ArkData';
// 初始化存储
const prefs = await preferences.getPreferences(this.context, 'streakData');
// 保存数据函数
async function saveStreakData(lastDate: string, streak: number) {
await prefs.putString('lastDate', lastDate);
await prefs.putNumber('currentStreak', streak);
await prefs.flush();
}
2. 核心逻辑判断
打卡时进行日期连续性判断:
import { util } from '@kit.ArkTS';
async function checkIn() {
// 获取当前日期(格式化为YYYY-MM-DD)
const today = new util.DateTime().toString().split('T')[0];
// 读取历史数据
const lastDate = await prefs.getString('lastDate', '');
let currentStreak = await prefs.getNumber('currentStreak', 0);
if (lastDate === '') {
// 首次打卡
currentStreak = 1;
} else {
const last = new Date(lastDate);
const current = new Date(today);
const diffDays = Math.floor((current.getTime() - last.getTime()) / (1000 * 3600 * 24));
if (diffDays === 1) {
// 连续打卡
currentStreak += 1;
} else if (diffDays === 0) {
// 今天已打卡
return currentStreak;
} else {
// 中断后重新开始
currentStreak = 1;
}
}
// 保存新状态
await saveStreakData(today, currentStreak);
return currentStreak;
}
3. 获取展示数据
提供获取当前连续天数的接口:
async function getCurrentStreak(): Promise<number> {
return await prefs.getNumber('currentStreak', 0);
}
async function getLastCheckInDate(): Promise<string> {
return await prefs.getString('lastDate', '');
}
4. 高级特性(可选)
- 历史记录:使用关系型数据库存储详细打卡记录,支持数据分析和图表展示
- 定时任务:通过后台任务检查打卡连续性,发送提醒通知
- 多设备同步:结合分布式数据管理实现跨设备打卡状态同步
注意事项
- 时区处理:确保使用用户本地时区进行日期计算
- 数据安全:敏感数据建议使用加密存储
- 性能优化:频繁操作建议批量写入
此方案通过最小化的数据存储和清晰的逻辑判断,即可实现可靠的连续打卡统计功能。

