旅行记录应用行程规划 - Cordova & OpenHarmony 混合开发实战
摘要:本文介绍了开源鸿蒙跨平台开发者社区中行程规划功能的实现方案。该功能允许用户创建详细的旅行日程安排,包括活动、景点、餐厅等信息。系统采用Cordova与OpenHarmony混合开发框架,提供日历视图和列表视图两种展示方式。文章详细阐述了数据模型设计、视图展示和原生层集成的完整流程,并提供了Web端的HTML结构和JavaScript代码实现,包括行程加载、活动列表渲染和活动保存等核心功能。通
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
📌 概述
行程规划功能允许用户为旅行创建详细的日程安排。用户可以为每一天添加活动、景点、餐厅等信息,形成完整的行程计划。行程规划提供了日历视图和列表视图,用户可以灵活地查看和编辑行程。在 Cordova 与 OpenHarmony 的混合开发框架中,行程规划需要实现日程管理和日历展示功能。
🔗 完整流程
第一步:日程数据模型设计
行程规划需要为每一天的活动创建数据模型。每个活动包括时间、地点、描述、类型等信息。活动需要与旅行关联,一个旅行可以有多个活动。
第二步:日程列表与日历展示
行程规划页面需要提供两种视图:列表视图和日历视图。列表视图按时间顺序展示所有活动,日历视图在日历上标记有活动的日期。
第三步:原生层日历集成与提醒
OpenHarmony 原生层可以集成系统日历,将行程同步到系统日历。原生层还可以实现行程提醒功能,在活动开始前通知用户。
🔧 Web 代码实现
行程规划页面 HTML 结构
<div id="itinerary-page" class="page">
<div class="page-header">
<h1>行程规划</h1>
<button class="btn btn-primary" onclick="openActivityModal()">
➕ 添加活动
</button>
</div>
<div class="itinerary-container">
<div class="view-toggle">
<button class="btn-toggle active" onclick="switchView('list')">列表视图</button>
<button class="btn-toggle" onclick="switchView('calendar')">日历视图</button>
</div>
<div id="listView" class="itinerary-list">
<!-- 活动列表动态加载 -->
</div>
<div id="calendarView" class="itinerary-calendar" style="display: none;">
<!-- 日历视图动态加载 -->
</div>
</div>
</div>
HTML 结构包含列表视图和日历视图的切换。
加载行程函数
async function loadItinerary(tripId) {
try {
// 获取旅行数据
const trip = await db.getTrip(tripId);
// 获取所有活动
const activities = await db.getActivitiesByTrip(tripId);
// 按日期排序
activities.sort((a, b) => new Date(a.date) - new Date(b.date));
// 渲染列表视图
renderActivityList(activities, trip);
// 渲染日历视图
renderCalendarView(activities, trip);
} catch (error) {
console.error('Error loading itinerary:', error);
showToast('加载行程失败');
}
}
这个函数加载旅行的所有活动,然后渲染两种视图。loadItinerary 函数是行程规划的核心加载函数。函数首先从数据库获取旅行数据,然后获取该旅行的所有活动。接着按照活动的日期进行排序,确保活动按时间顺序显示。然后调用 renderActivityList 函数渲染列表视图,用户可以看到按日期分组的所有活动。同时调用 renderCalendarView 函数渲染日历视图,用户可以在日历上看到有活动的日期。这种双视图设计提供了灵活的查看方式,用户可以根据需要选择合适的视图。通过这个函数,用户可以全面了解旅行的行程安排。
活动列表渲染函数
function renderActivityList(activities, trip) {
const container = document.getElementById('listView');
container.innerHTML = '';
// 按日期分组
const groupedActivities = {};
activities.forEach(activity => {
const date = activity.date;
if (!groupedActivities[date]) {
groupedActivities[date] = [];
}
groupedActivities[date].push(activity);
});
// 渲染每一天的活动
Object.keys(groupedActivities).sort().forEach(date => {
const dayActivities = groupedActivities[date];
const dayElement = document.createElement('div');
dayElement.className = 'day-activities';
dayElement.innerHTML = `<h3>${formatDate(date)}</h3>`;
dayActivities.forEach(activity => {
const activityElement = document.createElement('div');
activityElement.className = 'activity-item';
activityElement.innerHTML = `
<div class="activity-time">${activity.time || '全天'}</div>
<div class="activity-content">
<h4>${activity.title}</h4>
<p>${activity.description || ''}</p>
<span class="activity-location">📍 ${activity.location || '未设置'}</span>
</div>
<div class="activity-actions">
<button class="btn-small" onclick="editActivity(${activity.id})">编辑</button>
<button class="btn-small btn-danger" onclick="deleteActivity(${activity.id})">删除</button>
</div>
`;
dayElement.appendChild(activityElement);
});
container.appendChild(dayElement);
});
}
活动列表渲染函数按日期分组展示所有活动。
保存活动函数
async function saveActivity(activityData) {
try {
// 验证数据
if (!activityData.title || activityData.title.trim() === '') {
showToast('活动标题不能为空');
return;
}
// 创建活动对象
const activity = {
id: activityData.id || Date.now(),
tripId: activityData.tripId,
title: activityData.title,
description: activityData.description,
date: activityData.date,
time: activityData.time,
location: activityData.location,
type: activityData.type,
createdAt: activityData.createdAt || new Date().toISOString(),
updatedAt: new Date().toISOString()
};
// 保存到数据库
if (activityData.id) {
await db.updateActivity(activity);
showToast('活动已更新');
} else {
await db.addActivity(activity);
showToast('活动已添加');
}
// 关闭模态框
closeModal();
// 重新加载行程
loadItinerary(activity.tripId);
// 通知原生层
if (window.cordova) {
cordova.exec(
(result) => console.log('Activity saved:', result),
(error) => console.error('Save error:', error),
'ItineraryPlugin',
'onActivitySaved',
[{ activityId: activity.id, tripId: activity.tripId, timestamp: Date.now() }]
);
}
} catch (error) {
console.error('Error saving activity:', error);
showToast('保存失败,请重试');
}
}
保存活动函数创建或更新活动,然后保存到数据库。
日历视图渲染函数
function renderCalendarView(activities, trip) {
const container = document.getElementById('calendarView');
container.innerHTML = '';
// 获取旅行的日期范围
const startDate = new Date(trip.startDate);
const endDate = new Date(trip.endDate);
// 创建日历
const calendar = document.createElement('div');
calendar.className = 'calendar';
// 获取有活动的日期
const activityDates = new Set(activities.map(a => a.date));
// 遍历每一天
let currentDate = new Date(startDate);
while (currentDate <= endDate) {
const dateStr = currentDate.toISOString().split('T')[0];
const dayElement = document.createElement('div');
dayElement.className = 'calendar-day';
if (activityDates.has(dateStr)) {
dayElement.classList.add('has-activity');
}
dayElement.innerHTML = `
<div class="day-number">${currentDate.getDate()}</div>
<div class="day-activities-count">
${activities.filter(a => a.date === dateStr).length}
</div>
`;
calendar.appendChild(dayElement);
currentDate.setDate(currentDate.getDate() + 1);
}
container.appendChild(calendar);
}
日历视图渲染函数在日历上标记有活动的日期。
🔌 OpenHarmony 原生代码实现
行程规划插件
// ItineraryPlugin.ets
import { BusinessError } from '@ohos.base';
export class ItineraryPlugin {
// 处理活动保存事件
onActivitySaved(args: any, callback: Function): void {
try {
const activityId = args[0].activityId;
const tripId = args[0].tripId;
const timestamp = args[0].timestamp;
console.log(`[Itinerary] Activity saved: ${activityId} for trip ${tripId}`);
callback({ success: true, message: '活动已保存' });
} catch (error) {
callback({ success: false, error: error.message });
}
}
// 设置活动提醒
setActivityReminder(args: any, callback: Function): void {
try {
const activityId = args[0].activityId;
const reminderTime = args[0].reminderTime;
console.log(`[Itinerary] Reminder set for activity ${activityId}`);
callback({ success: true, message: '提醒已设置' });
} catch (error) {
callback({ success: false, error: error.message });
}
}
}
行程规划插件处理活动保存和提醒设置。
📝 总结
行程规划功能展示了如何在 Cordova 与 OpenHarmony 框架中实现一个完整的日程管理系统。Web 层负责 UI 渲染和日程操作,原生层负责提醒管理。通过行程规划,用户可以详细规划旅行的每一天。
更多推荐

所有评论(0)