在这里插入图片描述

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

本文对应模块:Web 层的日历视图与时间管理实现,包括日历渲染、日期任务查询、月份导航、与原生层的日期事件同步机制。

📌 概述

日历视图是任务管理应用的重要功能,提供了一种直观的方式来查看和管理按日期组织的任务。日历视图包括日历渲染、日期任务查询、月份导航等功能。CalendarManager 类是日历管理的核心,负责计算日历数据和任务统计。通过日历视图,用户可以清晰地看到每个日期的任务情况,便于时间管理。

🔗 日历视图的完整流程

日历视图分为三层:Web 层的 CalendarManager(日历管理器)负责日历计算和任务查询,TaskManager(任务管理器)负责获取任务数据,DatabaseModule(数据库模块)负责数据的持久化。当用户打开日历视图时,CalendarManager 计算当前月份的日历数据,包括每天的任务数量和完成情况。当用户切换月份时,CalendarManager 重新计算新月份的日历数据。当用户点击某个日期时,CalendarManager 获取该日期的所有任务并显示。

日历视图与任务列表不同,它以日期为中心组织任务。用户可以快速看到某个日期有多少任务,以及这些任务的完成情况。这对于时间规划和任务分配非常有用。例如,用户可以看到某个日期有 5 个任务,其中 2 个已完成,3 个待完成。通过日历视图,用户可以平衡每天的工作量,避免某些日期任务过多。

日历视图的实现需要考虑以下几个方面:首先是日历的计算,需要正确计算每个月份的天数和第一天是星期几。其次是任务的查询,需要按日期查询任务。第三是任务的统计,需要统计每个日期的任务数量和完成情况。第四是月份导航,需要支持上一个月、下一个月和回到今天的功能。最后是与原生层的集成,需要通过 Cordova 插件将日期事件通知给原生层。

日历视图在实际应用中非常重要。用户可以通过日历视图快速了解整个月份的任务分布,从而更好地规划时间。日历视图还可以帮助用户识别任务堆积的日期,及时调整任务分配。通过日历视图,用户可以实现更科学的时间管理。日历视图还支持快速跳转到特定日期,用户可以点击日期快速查看该日期的所有任务。日历视图的颜色编码可以帮助用户一目了然地看到任务的完成情况,例如绿色表示全部完成,黄色表示部分完成,红色表示全部未完成。

🔧 日历管理器实现

日历管理器的核心实现包括日历计算、任务查询、月份导航等功能。日历计算时需要正确处理闰年和月份的天数。任务查询时需要按日期过滤任务。月份导航时需要更新当前日期并重新计算日历数据。

// 日历管理器的关键方法
class CalendarManager {
    constructor() {
        this.currentDate = new Date();
    }

    getDaysInMonth(date) {
        return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
    }

    getFirstDayOfMonth(date) {
        return new Date(date.getFullYear(), date.getMonth(), 1).getDay();
    }

    getTasksByDate(date) {
        const dateStr = date.toISOString().split('T')[0];
        return taskManager.getAllTasks().filter(t => t.dueDate === dateStr);
    }

    getMonthStats(date) {
        const stats = {};
        const daysInMonth = this.getDaysInMonth(date);
        for (let day = 1; day <= daysInMonth; day++) {
            const currentDate = new Date(date.getFullYear(), date.getMonth(), day);
            const tasks = this.getTasksByDate(currentDate);
            stats[day] = {
                total: tasks.length,
                completed: tasks.filter(t => t.status === 'completed').length,
                pending: tasks.filter(t => t.status === 'pending').length
            };
        }
        return stats;
    }

    previousMonth() {
        this.currentDate.setMonth(this.currentDate.getMonth() - 1);
    }

    nextMonth() {
        this.currentDate.setMonth(this.currentDate.getMonth() + 1);
    }

    goToToday() {
        this.currentDate = new Date();
    }
}

const calendarManager = new CalendarManager();

代码解释:

CalendarManager 类提供了日历管理的核心功能。getDaysInMonth() 方法计算指定月份的天数,通过创建下个月的第 0 天来获取当月的最后一天。getFirstDayOfMonth() 方法获取指定月份的第一天是星期几,返回值 0-6 分别代表周日到周六。getTasksByDate() 方法获取指定日期的所有任务,通过将日期转换为 YYYY-MM-DD 格式的字符串,然后过滤任务列表。getMonthStats() 方法计算整个月份的任务统计,对每一天都计算任务总数、已完成数和待完成数。previousMonth() 和 nextMonth() 方法实现月份导航,通过修改 currentDate 的月份值。goToToday() 方法将当前日期重置为今天。

🔌 原生层的日历事件同步

HarmonyOS 原生层也需要与 Web 层的日历视图进行集成。原生层可以通过 Cordova 插件来接收来自 Web 层的日期事件。

// ArkTS 代码示例 - 日历同步插件
import { CordovaPlugin, CallbackContext } from '@magongshou/harmony-cordova/Index';
import { PluginResult, MessageStatus } from '@magongshou/harmony-cordova/Index';

export class CalendarSyncPlugin extends CordovaPlugin {
    // 监听 Web 层的日期选择事件
    async onDateSelected(callbackContext: CallbackContext, args: string[]): Promise<void> {
        try {
            const dateData = JSON.parse(args[0]);
            console.log('[CalendarSyncPlugin] 日期已选择:', dateData.date);
            console.log('[CalendarSyncPlugin] 该日期任务数:', dateData.taskCount);
            
            const result = PluginResult.createByString(MessageStatus.OK, '日期已同步');
            callbackContext.sendPluginResult(result);
        } catch (error) {
            const result = PluginResult.createByString(MessageStatus.ERROR, (error as Error).message);
            callbackContext.sendPluginResult(result);
        }
    }

    // 监听 Web 层的月份切换事件
    async onMonthChanged(callbackContext: CallbackContext, args: string[]): Promise<void> {
        try {
            const monthData = JSON.parse(args[0]);
            console.log('[CalendarSyncPlugin] 月份已切换:', monthData.year, monthData.month);
            
            const result = PluginResult.createByString(MessageStatus.OK, '月份已同步');
            callbackContext.sendPluginResult(result);
        } catch (error) {
            const result = PluginResult.createByString(MessageStatus.ERROR, (error as Error).message);
            callbackContext.sendPluginResult(result);
        }
    }

    // 监听 Web 层的任务统计更新
    async onStatsUpdated(callbackContext: CallbackContext, args: string[]): Promise<void> {
        try {
            const statsData = JSON.parse(args[0]);
            console.log('[CalendarSyncPlugin] 统计已更新:', statsData.totalTasks, '个任务');
            
            const result = PluginResult.createByString(MessageStatus.OK, '统计已同步');
            callbackContext.sendPluginResult(result);
        } catch (error) {
            const result = PluginResult.createByString(MessageStatus.ERROR, (error as Error).message);
            callbackContext.sendPluginResult(result);
        }
    }
}

原生代码解释:

CalendarSyncPlugin 是一个 Cordova 插件,提供了原生层与 Web 层日历视图的交互接口。onDateSelected 方法监听 Web 层的日期选择事件,接收选中的日期和该日期的任务数。原生层可以根据这个事件更新原生层的日期显示或执行其他操作。onMonthChanged 方法监听 Web 层的月份切换事件,接收新的年份和月份。原生层可以根据这个事件同步原生层的日历显示。onStatsUpdated 方法监听 Web 层的任务统计更新,接收统计数据。原生层可以根据这个事件更新原生层的统计显示。

Web 层通知原生日期事件

Web 层可以调用原生插件来通知原生层日期相关的事件:

// JavaScript 代码 - 通知原生日期事件
function notifyDateSelected(date, taskCount) {
    cordova.exec(
        function() { console.log('原生层已收到日期选择通知'); },
        function(error) { console.error('通知失败:', error); },
        'CalendarSyncPlugin',
        'onDateSelected',
        [JSON.stringify({ date, taskCount })]
    );
}

function notifyMonthChanged(year, month) {
    cordova.exec(
        function() { console.log('原生层已收到月份切换通知'); },
        function(error) { console.error('通知失败:', error); },
        'CalendarSyncPlugin',
        'onMonthChanged',
        [JSON.stringify({ year, month })]
    );
}

function notifyStatsUpdated(totalTasks, completedTasks) {
    cordova.exec(
        function() { console.log('原生层已收到统计更新通知'); },
        function(error) { console.error('通知失败:', error); },
        'CalendarSyncPlugin',
        'onStatsUpdated',
        [JSON.stringify({ totalTasks, completedTasks })]
    );
}

Web 层代码解释:

notifyDateSelected 函数使用 cordova.exec() 调用原生插件的 onDateSelected 方法,传递选中的日期和任务数。这样可以从 Web 层通知原生层用户选择了某个日期。notifyMonthChanged 函数调用原生插件的 onMonthChanged 方法,传递新的年份和月份。这样可以从 Web 层通知原生层用户切换了月份。notifyStatsUpdated 函数调用原生插件的 onStatsUpdated 方法,传递任务统计数据。这样可以从 Web 层通知原生层任务统计已更新。通过这些函数,Web 层可以将日历相关的事件同步给原生层,使原生层能够保持与 Web 层的数据一致。

📝 总结

日历视图是应用的重要功能,通过直观的日期展示,用户可以快速了解任务分布。通过与原生层的集成,可以实现日期事件的完整同步,使用户在不同层级都能看到最新的日历信息。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐