news 2026/5/26 7:32:23

旅行记录应用新建旅行 - Cordova OpenHarmony 混合开发实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
旅行记录应用新建旅行 - Cordova OpenHarmony 混合开发实战

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

📌 概述

新建旅行功能允许用户创建新的旅行记录。用户需要填写旅行的基本信息,如目的地、开始日期、结束日期、花费等。新建旅行页面提供了表单验证、自动保存、图片上传等功能。在 Cordova 与 OpenHarmony 的混合开发框架中,新建旅行需要实现完整的表单处理和原生层的文件上传功能。

🔗 完整流程

第一步:表单设计与验证

新建旅行表单需要包含所有必要的字段,并进行客户端验证。验证包括检查必填字段、日期有效性、花费格式等。表单还需要支持自动保存功能,防止用户数据丢失。

第二步:数据保存与关联

表单数据需要保存到数据库,并与目的地、标签、同行者等进行关联。保存过程需要进行事务处理,确保数据的一致性。

第三步:原生层文件上传与图片处理

OpenHarmony 原生层可以实现文件选择、图片上传、图片压缩等功能。原生层还可以实现图片的本地存储和缓存管理。

🔧 Web 代码实现

新建旅行页面 HTML 结构

<divid="new-trip-page"class="page"><divclass="page-header"><h1>新建旅行</h1></div><formid="newTripForm"class="trip-form"><divclass="form-group"><label>目的地 *</label><inputtype="text"name="destination"requiredplaceholder="输入目的地..."></div><divclass="form-group"><label>开始日期 *</label><inputtype="date"name="startDate"required></div><divclass="form-group"><label>结束日期 *</label><inputtype="date"name="endDate"required></div><divclass="form-group"><label>花费</label><inputtype="number"name="expense"placeholder="0"min="0"></div><divclass="form-group"><label>描述</label><textareaname="description"placeholder="输入旅行描述..."></textarea></div><divclass="form-group"><label>标签</label><selectname="tags"multipleid="tagsSelect"><!-- 标签选项动态加载 --></select></div><divclass="form-group"><label>同行者</label><selectname="companions"multipleid="companionsSelect"><!-- 同行者选项动态加载 --></select></div><divclass="form-group"><label>上传图片</label><inputtype="file"name="images"multipleaccept="image/*"onchange="handleImageUpload(event)"><divid="imagePreview"class="image-preview"></div></div><divclass="form-actions"><buttontype="button"class="btn btn-primary"onclick="saveTrip()">保存</button><buttontype="button"class="btn btn-secondary"onclick="navigateTo('all-trips')">取消</button></div></form></div>

HTML 结构包含所有必要的表单字段和图片上传功能。

初始化表单函数

asyncfunctioninitNewTripForm(){try{// 加载标签选项consttags=awaitdb.getAllTags();consttagsSelect=document.getElementById('tagsSelect');tags.forEach(tag=>{constoption=document.createElement('option');option.value=tag.id;option.textContent=tag.name;tagsSelect.appendChild(option);});// 加载同行者选项constcompanions=awaitdb.getAllCompanions();constcompanionsSelect=document.getElementById('companionsSelect');companions.forEach(companion=>{constoption=document.createElement('option');option.value=companion.id;option.textContent=companion.name;companionsSelect.appendChild(option);});// 设置默认日期consttoday=newDate().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('初始化表单失败');}}

初始化函数加载标签和同行者选项,设置默认日期。

表单验证函数

functionvalidateTripForm(){constform=document.getElementById('newTripForm');constdestination=form.querySelector('input[name="destination"]').value.trim();conststartDate=form.querySelector('input[name="startDate"]').value;constendDate=form.querySelector('input[name="endDate"]').value;// 检查必填字段if(!destination){showToast('请输入目的地');returnfalse;}if(!startDate){showToast('请选择开始日期');returnfalse;}if(!endDate){showToast('请选择结束日期');returnfalse;}// 检查日期有效性conststart=newDate(startDate);constend=newDate(endDate);if(start>end){showToast('开始日期不能晚于结束日期');returnfalse;}returntrue;}

表单验证函数检查必填字段和日期有效性。validateTripForm 函数是表单验证的核心函数。函数首先获取表单中的关键字段值,包括目的地、开始日期和结束日期。然后进行多层次的验证:首先检查必填字段是否为空,如果为空则显示相应的错误提示。然后检查日期的有效性,确保开始日期不晚于结束日期。这种分步验证方式提供了清晰的错误提示,帮助用户快速定位问题。通过这个函数,可以确保用户输入的数据是有效的,避免保存无效数据到数据库。

保存旅行函数

asyncfunctionsaveTrip(){// 验证表单if(!validateTripForm()){return;}try{// 获取表单数据constform=document.getElementById('newTripForm');constformData=newFormData(form);// 创建旅行对象consttrip={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:newDate().toISOString(),updatedAt:newDate().toISOString()};// 保存到数据库awaitdb.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('保存失败,请重试');}}

保存旅行函数验证表单,然后将数据保存到数据库。

图片上传处理函数

functionhandleImageUpload(event){constfiles=event.target.files;constpreview=document.getElementById('imagePreview');preview.innerHTML='';for(letfileoffiles){// 验证文件类型if(!file.type.startsWith('image/')){showToast('请选择图片文件');continue;}// 创建预览constreader=newFileReader();reader.onload=(e)=>{constimg=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.etsimport{BusinessError}from'@ohos.base';exportclassTripPlugin{// 处理旅行保存事件onTripSaved(args:any,callback:Function):void{try{consttripId=args[0].tripId;consttimestamp=args[0].timestamp;console.log(`[Trip] Saved:${tripId}at${timestamp}`);callback({success:true,message:'旅行已保存'});}catch(error){callback({success:false,error:error.message});}}}

旅行保存插件处理旅行保存事件。

图片上传插件

// ImagePlugin.etsimport{BusinessError}from'@ohos.base';import{fileIo}from'@kit.CoreFileKit';exportclassImagePlugin{// 上传图片uploadImages(args:any,callback:Function):void{try{constfileCount=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 和验证,原生层负责文件上传和图片处理。通过新建旅行功能,用户可以轻松创建新的旅行记录。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 4:53:23

8个降AI率工具,专科生必备避坑指南

8个降AI率工具&#xff0c;专科生必备避坑指南 AI降重工具&#xff1a;专科生论文写作的“隐形助手” 随着人工智能技术在学术领域的广泛应用&#xff0c;越来越多的专科生开始面临一个共同的难题——如何降低论文中的AIGC率&#xff0c;同时保持内容的逻辑性和语义通顺。尤其是…

作者头像 李华
网站建设 2026/5/25 17:33:18

C语言、C++、C#、VB语言对比探究,我们该如何选择?

C语言、C、C#、VB语言对比探究 一、概述 这四种语言代表了编程语言发展的不同阶段和设计哲学&#xff1a; C语言&#xff1a;面向过程的系统级编程语言C&#xff1a;多范式语言&#xff0c;支持面向过程和面向对象C#&#xff1a;完全面向对象的现代编程语言VB&#xff1a;基于.…

作者头像 李华
网站建设 2026/5/26 4:56:28

高性价比云手机 多端同步

云手机是基于端云一体虚拟化技术&#xff0c;将手机的核心计算、存储功能迁移至云端服务器的 “虚拟手机”&#xff0c;它通过在服务器上构建独立手机操作系统实例&#xff0c;用户可通过普通终端远程访问和操控&#xff0c;无需消耗过多本地硬件资源。云手机依托云端的计算和存…

作者头像 李华
网站建设 2026/5/26 6:11:35

GROUP BY进阶用法

问题重新: sql语句中使用了GROUP BY wf_cur.REQUESTID, wf_cur.NODEID,为什么还会出用两行相同REQUESTID的记录呢&#xff0c;GROUP BY不就是拿某个字段来分组吗&#xff1f;GROUP BY 是按你指定的字段组合进行分组的&#xff0c;不是按单个字段。你的例子&#xff1a;sqlGROUP…

作者头像 李华
网站建设 2026/5/25 20:08:16

Xiaomi MiMo-V2-Flash 开源:高效推理、代码与 Agent 基座模型

Xiaomi MiMo-V2-Flash 是小米专为极致推理效率自研的总参数 309B&#xff08;激活15B&#xff09;的 MoE 模型&#xff0c;通过引入 Hybrid 注意力架构创新 及 多层 MTP 推理加速&#xff0c;在多个 Agent 测评基准上进入全球开源模型 Top 2&#xff1b;代码能力超过所有开源模…

作者头像 李华