在这里插入图片描述

一、功能概述

在喝水记录应用中,用户最常用的操作是“快速记一杯水”。本篇文章围绕“快速记录喝水”页面展开,展示如何在 Cordova Web 层 使用表单收集数据、写入本地 IndexedDB,再通过 OpenHarmony ArkTS 插件 将本次饮水事件同步给原生层,用于触发通知、动画或小组件更新。全文依旧采用 一段代码 + 一段文字说明 的方式进行拆解,避免出现大段代码影响阅读。

二、Web 表单结构与基础样式

<form id="quick-drink-form" class="quick-form">
  <label class="form-item">
    <span>本次饮水量 (ml)</span>
    <input type="number" id="input-amount" min="50" step="50" value="250" required />
  </label>

  <label class="form-item">
    <span>饮水类型</span>
    <select id="select-type">
      <option value="water">白开水</option>
      <option value="tea">茶水</option>
      <option value="juice">果汁</option>
    </select>
  </label>

  <button type="submit" class="btn-primary">立即记录</button>
</form>

这段 HTML 定义了一个最小可用的“快速记录喝水”表单。quick-drink-form 是整个表单容器,内部包含饮水量输入框、饮水类型下拉选择以及一个提交按钮。饮水量使用 type="number",并设置 minstep 来约束输入范围和步长,使得用户在移动端和 PC 端都能方便地调整数值。下拉框 select-type 提供几种常见饮水类型,后续可以扩展为从数据库动态加载。通过在每个表单项外部包裹一个 label.form-item,可以让标题和控件在 CSS 中统一布局和对齐。

.quick-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 320px;
}

.form-item span {
  display: block;
  margin-bottom: 4px;
  font-size: 14px;
}

.form-item input,
.form-item select {
  width: 100%;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #4b5563;
  background-color: #111827;
  color: #e5e7eb;
}

这段 CSS 为快速记录表单提供了简单而实用的视觉样式。.quick-form 使用纵向 flex 布局,让每个表单项顺序排列并保持统一间距;max-width 控制表单整体宽度,既适合在 PC 上显示,又不会在窄屏设备上显得过于拥挤。每个 span 标签作为字段标题,使用 display: block 让标题和输入控件分行显示;输入框和下拉框统一设置了圆角、边框和背景色,与仪表板的深色主题保持一致。通过分离结构和样式,表单逻辑可以在不改动 HTML 的情况下灵活调整视觉效果。

三、表单提交与本地数据库写入

function bindQuickDrinkForm() {
  const form = document.getElementById('quick-drink-form');
  if (!form) return;

  form.addEventListener('submit', async (event) => {
    event.preventDefault();

    const amountInput = document.getElementById('input-amount') as HTMLInputElement | null;
    const typeSelect = document.getElementById('select-type') as HTMLSelectElement | null;

    const amount = Number(amountInput?.value || 0);
    const drinkType = typeSelect?.value || 'water';

    if (!amount || amount <= 0) {
      alert('请输入正确的饮水量');
      return;
    }

    const now = new Date();
    const record = {
      id: now.getTime(),
      date: now.toISOString(),
      amount,
      type: drinkType,
    };

    await db.addDrinkRecord(record);

    amountInput!.value = '250';
    syncQuickRecordToNative(record);
  });
}

bindQuickDrinkForm 函数负责给表单绑定提交事件,并在用户点击“立即记录”时完成数据收集与本地写入。首先通过 getElementById 获取表单和各个字段控件,在监听函数中调用 preventDefault 阻止浏览器默认的表单提交行为。随后读取饮水量与类型,并通过简单的合法性校验(例如 amount > 0)保证数据合理。如果校验失败,则通过 alert 向用户提示错误。

在构造 record 对象时,使用当前时间戳 now.getTime() 作为简单的主键,同时保存 ISO 格式日期、饮水量和类型。调用 db.addDrinkRecord 将记录写入 IndexedDB,这里假定数据库模块已经封装好了插入逻辑。写入完成后,将输入框重置为默认值 250,同时调用 syncQuickRecordToNative,把新记录同步给原生层,为后续的通知或动画提供依据。

document.addEventListener('DOMContentLoaded', () => {
  bindQuickDrinkForm();
});

为了确保表单元素已经出现在 DOM 中,这段代码在 DOMContentLoaded 事件触发后执行 bindQuickDrinkForm。和 deviceready 不同,DOMContentLoaded 只关心文档结构是否已经解析完成,适合用于绑定纯 Web 事件处理逻辑。通过把绑定代码与业务逻辑分离,可以保证当页面结构发生变化时,只要保持相同的 id,就不需要大幅修改事件绑定部分。

四、通过 Cordova 将单条记录同步到原生

function syncQuickRecordToNative(record) {
  if (!window.cordova) {
    console.warn('[QuickDrink] cordova not ready, skip native sync');
    return;
  }

  cordova.exec(
    () => {
      console.info('[QuickDrink] sync record success');
    },
    (err) => {
      console.error('[QuickDrink] sync record failed', err);
    },
    'WaterTrackerQuickDrink',
    'addRecord',
    [record]
  );
}

syncQuickRecordToNative 负责将刚刚保存到 IndexedDB 的饮水记录通过 Cordova 桥接发送到 ArkTS 插件中。这里同样首先检查 window.cordova 是否存在,如果 Cordova 尚未注入,就打印警告并终止流程,避免在不合适的时机调用导致异常。cordova.exec 的参数分别是成功回调、失败回调、插件名称、动作名称以及参数数组。本例中插件名设为 WaterTrackerQuickDrink,动作名为 addRecord,以便在 ArkTS 侧实现对应的方法。成功和失败回调中统一打印日志,为后续问题排查提供基础信息。

通过这种模式,Web 层在完成本地持久化之后,再把同一份记录推送给原生层,保证两端数据的一致性。原生层可以决定是否将这条记录用于刷新桌面小组件、展示动画或触发本地通知,而不需要 Web 层知道具体实现细节,从而实现职责分离。

五、OpenHarmony ArkTS 插件处理单条记录

// entry/src/main/ets/plugins/WaterTrackerQuickDrinkPlugin.ets
import common from '@ohos.app.ability.common';

export default class WaterTrackerQuickDrinkPlugin {
  context: common.UIAbilityContext;

  constructor(ctx: common.UIAbilityContext) {
    this.context = ctx;
  }

  addRecord(args: Array<Object>, callbackId: number) {
    const record = args[0] as {
      id: number;
      date: string;
      amount: number;
      type: string;
    };

    console.info(`[QuickDrinkPlugin] Receive record amount=${record.amount}, type=${record.type}`);
    // 这里可以进一步把数据存入本地首选项或触发通知
  }
}

这段 ArkTS 代码定义了一个接收单条饮水记录的插件 WaterTrackerQuickDrinkPlugin。在构造函数中,同样保存 UIAbilityContext 供后续使用;addRecord 方法按照 Cordova 的约定签名接收参数数组与回调编号,并从 args[0] 中解析出记录对象。这里给出了 iddateamounttype 的字段定义,方便在 TypeScript 级别获得更好的类型检查。当前示例中仅通过 console.info 打印了一条日志,说明已经成功收到了来自 Web 的饮水记录。在实际项目中,可以在这个方法中进一步:

  • 写入 ArkTS 侧自己的轻量数据存储;
  • 触发一个本地通知,提醒用户喝水进度;
  • 更新与喝水相关的桌面小组件或卡片。

把这些逻辑放在原生层可以减少 Web 层对系统能力的直接依赖,也能更充分地利用 HarmonyOS 提供的本地能力和资源管理机制。

六、ArkUI 页面中响应最新饮水记录

// entry/src/main/ets/pages/LatestDrinkPage.ets
@Component
struct LatestDrinkCard {
  @State amount: number = 0;
  @State drinkType: string = '';

  build() {
    Column() {
      Text('最近一次喝水')
        .fontSize(18)
        .margin({ bottom: 8 });

      Text(`饮水量:${this.amount} ml`)
        .fontSize(16);

      Text(`类型:${this.drinkType}`)
        .fontSize(16)
        .margin({ top: 4 });
    }
    .padding(16)
  }
}

LatestDrinkCard 是一个简单的 ArkUI 组件,用于展示“最近一次喝水”的信息。组件内部使用两个 @State 状态变量 amountdrinkType 保存最新的饮水量与类型。build 方法中,使用 Column 进行纵向布局,依次渲染标题、饮水量和饮水类型三行文本。通过字符串模板将状态变量插入到 Text 中,当状态改变时界面会自动刷新。这里没有直接展示状态更新逻辑,而是假设插件在接收到新记录后,会通过某种共享状态机制或消息分发系统把最新数据推送给该组件,对应的状态更新代码可以在后续扩展中补充。

这样的 ArkUI 组件可以嵌入到主页面或单独页面中,使原生界面能够实时反映用户最近一次的喝水情况。与 Web 层的表单配合,就构成了从输入到展示的完整闭环。

七、小结

本篇文章介绍了“快速记录喝水”功能在 Cordova 与 OpenHarmony 混合应用中的典型实现流程。首先在 Web 侧通过一个简洁的表单收集饮水量和类型等数据,并将其写入 IndexedDB;随后使用 bindQuickDrinkForm 绑定表单提交事件,在校验通过后构造记录对象并调用 db.addDrinkRecord 进行持久化。紧接着,通过 syncQuickRecordToNative 使用 cordova.exec 将这条记录发送给 ArkTS 插件。

在鸿蒙侧,我们定义了 WaterTrackerQuickDrinkPlugin 插件,用来解析来自 Web 的记录对象,未来可以将其与本地通知、桌面卡片或者其他系统能力对接;同时给出了一个简单的 ArkUI 组件 LatestDrinkCard 作为展示层示例。通过一段代码一段说明的方式,可以清晰地看到每一步的职责:Web 负责表单交互和本地数据库,原生层负责系统能力与更丰富的 UI 表达。后续你可以基于同样的结构扩展更多字段(例如水温、容器类型等),或者为不同类型饮品设计不同的原生展示风格,从而在保持开发效率的同时,打造出更贴合用户习惯的喝水记录体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐