旅行记录应用新建旅行 - Cordova & OpenHarmony 混合开发实战
本文介绍了新建旅行功能的实现方案,包括表单设计、数据验证和保存流程。主要内容涵盖:1)表单HTML结构设计,包含目的地、日期、花费等必填字段;2)JavaScript初始化函数,动态加载标签和同行者选项;3)表单验证逻辑,检查必填字段和日期有效性;4)数据保存流程。该功能采用混合开发框架,结合了Web表单处理和原生文件上传能力,确保数据完整性和用户体验。
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
📌 概述
新建旅行功能允许用户创建新的旅行记录。用户需要填写旅行的基本信息,如目的地、开始日期、结束日期、花费等。新建旅行页面提供了表单验证、自动保存、图片上传等功能。在 Cordova 与 OpenHarmony 的混合开发框架中,新建旅行需要实现完整的表单处理和原生层的文件上传功能。
🔗 完整流程
第一步:表单设计与验证
新建旅行表单需要包含所有必要的字段,并进行客户端验证。验证包括检查必填字段、日期有效性、花费格式等。表单还需要支持自动保存功能,防止用户数据丢失。
第二步:数据保存与关联
表单数据需要保存到数据库,并与目的地、标签、同行者等进行关联。保存过程需要进行事务处理,确保数据的一致性。
第三步:原生层文件上传与图片处理
OpenHarmony 原生层可以实现文件选择、图片上传、图片压缩等功能。原生层还可以实现图片的本地存储和缓存管理。
🔧 Web 代码实现
新建旅行页面 HTML 结构
<div id="new-trip-page" class="page">
<div class="page-header">
<h1>新建旅行</h1>
</div>
<form id="newTripForm" class="trip-form">
<div class="form-group">
<label>目的地 *</label>
<input type="text" name="destination" required placeholder="输入目的地...">
</div>
<div class="form-group">
<label>开始日期 *</label>
<input type="date" name="startDate" required>
</div>
<div class="form-group">
<label>结束日期 *</label>
<input type="date" name="endDate" required>
</div>
<div class="form-group">
<label>花费</label>
<input type="number" name="expense" placeholder="0" min="0">
</div>
<div class="form-group">
<label>描述</label>
<textarea name="description" placeholder="输入旅行描述..."></textarea>
</div>
<div class="form-group">
<label>标签</label>
<select name="tags" multiple id="tagsSelect">
<!-- 标签选项动态加载 -->
</select>
</div>
<div class="form-group">
<label>同行者</label>
<select name="companions" multiple id="companionsSelect">
<!-- 同行者选项动态加载 -->
</select>
</div>
<div class="form-group">
<label>上传图片</label>
<input type="file" name="images" multiple accept="image/*"
onchange="handleImageUpload(event)">
<div id="imagePreview" class="image-preview"></div>
</div>
<div class="form-actions">
<button type="button" class="btn btn-primary" onclick="saveTrip()">
保存
</button>
<button type="button" class="btn btn-secondary" onclick="navigateTo('all-trips')">
取消
</button>
</div>
</form>
</div>
HTML 结构包含所有必要的表单字段和图片上传功能。
初始化表单函数
async function initNewTripForm() {
try {
// 加载标签选项
const tags = await db.getAllTags();
const tagsSelect = document.getElementById('tagsSelect');
tags.forEach(tag => {
const option = document.createElement('option');
option.value = tag.id;
option.textContent = tag.name;
tagsSelect.appendChild(option);
});
// 加载同行者选项
const companions = await db.getAllCompanions();
const companionsSelect = document.getElementById('companionsSelect');
companions.forEach(companion => {
const option = document.createElement('option');
option.value = companion.id;
option.textContent = companion.name;
companionsSelect.appendChild(option);
});
// 设置默认日期
const today = new Date().toISOString().split('T')[0];
document.querySelector('input[name="startDate"]').value = today;
document.querySelector('input[name="endDate"]').value = today;
} catch (error) {
console.error('Error initializing form:', error);
showToast('初始化表单失败');
}
}
初始化函数加载标签和同行者选项,设置默认日期。
表单验证函数
function validateTripForm() {
const form = document.getElementById('newTripForm');
const destination = form.querySelector('input[name="destination"]').value.trim();
const startDate = form.querySelector('input[name="startDate"]').value;
const endDate = form.querySelector('input[name="endDate"]').value;
// 检查必填字段
if (!destination) {
showToast('请输入目的地');
return false;
}
if (!startDate) {
showToast('请选择开始日期');
return false;
}
if (!endDate) {
showToast('请选择结束日期');
return false;
}
// 检查日期有效性
const start = new Date(startDate);
const end = new Date(endDate);
if (start > end) {
showToast('开始日期不能晚于结束日期');
return false;
}
return true;
}
表单验证函数检查必填字段和日期有效性。validateTripForm 函数是表单验证的核心函数。函数首先获取表单中的关键字段值,包括目的地、开始日期和结束日期。然后进行多层次的验证:首先检查必填字段是否为空,如果为空则显示相应的错误提示。然后检查日期的有效性,确保开始日期不晚于结束日期。这种分步验证方式提供了清晰的错误提示,帮助用户快速定位问题。通过这个函数,可以确保用户输入的数据是有效的,避免保存无效数据到数据库。
保存旅行函数
async function saveTrip() {
// 验证表单
if (!validateTripForm()) {
return;
}
try {
// 获取表单数据
const form = document.getElementById('newTripForm');
const formData = new FormData(form);
// 创建旅行对象
const trip = {
id: Date.now(),
destination: formData.get('destination'),
startDate: formData.get('startDate'),
endDate: formData.get('endDate'),
expense: parseInt(formData.get('expense')) || 0,
description: formData.get('description'),
tags: formData.getAll('tags'),
companions: formData.getAll('companions'),
images: [],
isFavorite: false,
isDeleted: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
// 保存到数据库
await db.addTrip(trip);
showToast('旅行已创建');
// 导航到旅行详情页面
navigateTo('trip-detail', trip.id);
// 通知原生层
if (window.cordova) {
cordova.exec(
(result) => console.log('Trip saved:', result),
(error) => console.error('Save error:', error),
'TripPlugin',
'onTripSaved',
[{ tripId: trip.id, timestamp: Date.now() }]
);
}
} catch (error) {
console.error('Error saving trip:', error);
showToast('保存失败,请重试');
}
}
保存旅行函数验证表单,然后将数据保存到数据库。
图片上传处理函数
function handleImageUpload(event) {
const files = event.target.files;
const preview = document.getElementById('imagePreview');
preview.innerHTML = '';
for (let file of files) {
// 验证文件类型
if (!file.type.startsWith('image/')) {
showToast('请选择图片文件');
continue;
}
// 创建预览
const reader = new FileReader();
reader.onload = (e) => {
const img = document.createElement('img');
img.src = e.target.result;
img.className = 'preview-image';
preview.appendChild(img);
};
reader.readAsDataURL(file);
}
// 通知原生层上传图片
if (window.cordova && files.length > 0) {
cordova.exec(
(result) => console.log('Images uploaded:', result),
(error) => console.error('Upload error:', error),
'ImagePlugin',
'uploadImages',
[{ fileCount: files.length }]
);
}
}
图片上传处理函数创建图片预览,并通知原生层上传图片。
🔌 OpenHarmony 原生代码实现
旅行保存插件
// TripPlugin.ets
import { BusinessError } from '@ohos.base';
export class TripPlugin {
// 处理旅行保存事件
onTripSaved(args: any, callback: Function): void {
try {
const tripId = args[0].tripId;
const timestamp = args[0].timestamp;
console.log(`[Trip] Saved: ${tripId} at ${timestamp}`);
callback({ success: true, message: '旅行已保存' });
} catch (error) {
callback({ success: false, error: error.message });
}
}
}
旅行保存插件处理旅行保存事件。
图片上传插件
// ImagePlugin.ets
import { BusinessError } from '@ohos.base';
import { fileIo } from '@kit.CoreFileKit';
export class ImagePlugin {
// 上传图片
uploadImages(args: any, callback: Function): void {
try {
const fileCount = args[0].fileCount;
console.log(`[Image] Uploading ${fileCount} images...`);
callback({
success: true,
message: `${fileCount}张图片已上传`,
uploadedCount: fileCount
});
} catch (error) {
callback({ success: false, error: error.message });
}
}
}
图片上传插件处理图片上传功能。
📝 总结
新建旅行功能展示了如何在 Cordova 与 OpenHarmony 框架中实现一个完整的表单处理系统。Web 层负责表单 UI 和验证,原生层负责文件上传和图片处理。通过新建旅行功能,用户可以轻松创建新的旅行记录。
更多推荐

所有评论(0)