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

在这里插入图片描述

📌 概述

基本设置模块为用户提供了配置应用全局行为的入口,包括应用语言、货币单位、默认排序方式、首页展示内容等。模块同时打通了 Web 层配置面板与 OpenHarmony 原生偏好存储,实现“前端 UI 修改 → 原生持久化 → 全局生效”的完整链路。所有设置项都被集中保存在 settings 表和原生 Preferences,应用启动时会统一加载并应用,保证行为一致。通过合理的分组与默认值设计,用户既可以开箱即用,也能根据自己的喝茶习惯和地区偏好进行深入定制。

🔗 完整流程

第一步:加载与合并配置

当用户打开“基本设置”页面时,前端会先从 IndexedDB 的 settings 表加载已有配置,如果是首次启动则返回空集合。随后通过 Cordova 调用 SettingsBridge 原生插件,从 OpenHarmony 的 Preferences 中读取系统级设置(例如是否允许使用系统深色模式、是否允许原生通知等),将两部分配置进行合并,得到一份“当前生效配置”。这一过程同时会填充表单默认值,例如语言下拉框选中“简体中文”、货币单位选中“CNY”、默认排序方式选中“按时间倒序”等,让用户一眼看到当前真实状态。

第二步:用户修改与即时预览

设置页上的每一个表单控件都绑定了本地状态,当用户修改语言、货币、默认页面或是否启用提示音等选项时,会立刻更新内存中的配置对象。部分设置(如默认排序方式、是否显示统计卡片)会直接在当前 Web 页面中即时生效,用于提供预览效果;而另一些需要重启或重新渲染的设置(如语言切换)则会给出“重启后生效”的提示。为了避免频繁写入数据库,前端会在“应用设置”按钮点击时集中提交一次,将所有变更打包发送给本地 IndexedDB 和原生插件。

第三步:持久化与全局应用

当用户点击“保存设置”时,前端会调用 db.saveSettings(settings) 将配置保存到 IndexedDB 中,并通过 cordova.exec 调用 SettingsBridge.saveNativeSettings() 在原生侧写入 Preferences。随后,主应用在下次启动或主动刷新配置时,会统一从本地数据库和 Preferences 加载这些设置,并应用到导航、统计模块、主题模块等多个子系统中,确保全局行为与用户选择保持一致。对于影响原生行为的选项(如是否允许震动提醒),原生插件会在注册通知或振动前读取对应配置,做到真正“按设置行事”。

🔧 Web 代码实现

基本设置页面 HTML 结构

<div id="basic-settings-page" class="page">
  <div class="page-header">
    <h1>基本设置</h1>
  </div>

  <form id="settings-form" class="form">
    <div class="form-group">
      <label for="setting-language">界面语言</label>
      <select id="setting-language" name="language">
        <option value="zh-CN">简体中文</option>
        <option value="en-US">English</option>
      </select>
    </div>

    <div class="form-group">
      <label for="setting-currency">货币单位</label>
      <select id="setting-currency" name="currency">
        <option value="CNY">人民币 (CNY)</option>
        <option value="USD">美元 (USD)</option>
        <option value="EUR">欧元 (EUR)</option>
      </select>
    </div>

    <div class="form-group">
      <label for="setting-default-page">默认首页</label>
      <select id="setting-default-page" name="defaultPage">
        <option value="dashboard">仪表板</option>
        <option value="record-list">记录列表</option>
        <option value="trend-analysis">趋势分析</option>
      </select>
    </div>

    <div class="form-group">
      <label>启动时加载统计卡片</label>
      <label class="switch">
        <input type="checkbox" id="setting-load-stats" name="loadStats">
        <span class="slider"></span>
      </label>
    </div>

    <div class="form-group">
      <label>启用震动反馈</label>
      <label class="switch">
        <input type="checkbox" id="setting-haptics" name="haptics">
        <span class="slider"></span>
      </label>
      <small class="form-text">需要系统支持,原生层将根据此开关决定是否调用震动服务。</small>
    </div>

    <div class="form-actions">
      <button type="button" class="btn btn-secondary" onclick="resetSettingsForm()">恢复默认</button>
      <button type="submit" class="btn btn-primary">保存设置</button>
    </div>
  </form>
</div>

这段 HTML 定义了“基本设置”页面的主要表单项:包括语言、货币、默认首页、是否加载统计卡片以及是否启用震动反馈等。使用 select 和自定义 switch 组件的组合,可以保持页面风格统一,同时保证键盘和可访问性友好。settings-form 表单稍后会在 JavaScript 中绑定 submit 事件以集中处理保存逻辑,而“恢复默认”按钮则用于一键回退到系统推荐设置。

设置加载、编辑与保存逻辑

let currentSettings = {
  language: 'zh-CN',
  currency: 'CNY',
  defaultPage: 'dashboard',
  loadStats: true,
  haptics: true
};

async function initBasicSettingsPage() {
  try {
    const saved = await db.getSettings();
    if (saved) {
      currentSettings = { ...currentSettings, ...saved };
    }

    if (window.cordova) {
      cordova.exec(
        native => {
          currentSettings = { ...currentSettings, ...native };
          fillSettingsForm();
        },
        () => fillSettingsForm(),
        'SettingsBridge',
        'loadNativeSettings',
        []
      );
    } else {
      fillSettingsForm();
    }

    document
      .getElementById('settings-form')
      .addEventListener('submit', handleSettingsSubmit);
  } catch (error) {
    console.error('Failed to init settings page:', error);
    showToast('加载设置失败', 'error');
    fillSettingsForm();
  }
}

function fillSettingsForm() {
  document.getElementById('setting-language').value = currentSettings.language;
  document.getElementById('setting-currency').value = currentSettings.currency;
  document.getElementById('setting-default-page').value = currentSettings.defaultPage;
  document.getElementById('setting-load-stats').checked = !!currentSettings.loadStats;
  document.getElementById('setting-haptics').checked = !!currentSettings.haptics;
}

async function handleSettingsSubmit(event) {
  event.preventDefault();

  const form = document.getElementById('settings-form');
  const formData = new FormData(form);

  const newSettings = {
    language: formData.get('language') || 'zh-CN',
    currency: formData.get('currency') || 'CNY',
    defaultPage: formData.get('defaultPage') || 'dashboard',
    loadStats: formData.get('loadStats') === 'on',
    haptics: formData.get('haptics') === 'on'
  };

  try {
    await db.saveSettings(newSettings);
    currentSettings = newSettings;

    if (window.cordova) {
      cordova.exec(
        () => console.log('Native settings saved'),
        err => console.error('Save native settings error:', err),
        'SettingsBridge',
        'saveNativeSettings',
        [newSettings]
      );
    }

    showToast('设置已保存', 'success');
  } catch (error) {
    console.error('Failed to save settings:', error);
    showToast('保存失败,请重试', 'error');
  }
}

function resetSettingsForm() {
  currentSettings = {
    language: 'zh-CN',
    currency: 'CNY',
    defaultPage: 'dashboard',
    loadStats: true,
    haptics: true
  };
  fillSettingsForm();
  showToast('已恢复默认设置,仅在保存后生效', 'info');
}

上面这段 JavaScript 代码实现了基本设置的整个前端流程:initBasicSettingsPage() 先从 IndexedDB 读取已有配置,再尝试从原生层加载补充设置,然后调用 fillSettingsForm() 将合并后的配置填入表单。handleSettingsSubmit() 在表单提交时收集用户输入、写回 settings 表,并通过 SettingsBridge.saveNativeSettings 同步到 ArkTS 原生层。resetSettingsForm() 则简单重置为一组约定好的默认值,并提示用户需要点击“保存设置”后才会真正持久化。

🔌 OpenHarmony 原生代码(ArkTS)

SettingsBridge:Preferences 持久化与读取

// entry/src/main/ets/plugins/SettingsBridge.ets
import preferences from '@ohos.data.preferences';

const PREF_NAME = 'tea_app_settings';

export class SettingsBridge {
  static async loadNativeSettings(): Promise<Record<string, unknown>> {
    const pref = await preferences.getPreferences(globalThis.context, PREF_NAME);

    const language = await pref.get('language', 'zh-CN') as string;
    const currency = await pref.get('currency', 'CNY') as string;
    const defaultPage = await pref.get('defaultPage', 'dashboard') as string;
    const loadStats = await pref.get('loadStats', true) as boolean;
    const haptics = await pref.get('haptics', true) as boolean;

    return { language, currency, defaultPage, loadStats, haptics };
  }

  static async saveNativeSettings(settings: Record<string, unknown>): Promise<void> {
    const pref = await preferences.getPreferences(globalThis.context, PREF_NAME);

    if (settings.language !== undefined) {
      await pref.put('language', settings.language as string);
    }
    if (settings.currency !== undefined) {
      await pref.put('currency', settings.currency as string);
    }
    if (settings.defaultPage !== undefined) {
      await pref.put('defaultPage', settings.defaultPage as string);
    }
    if (settings.loadStats !== undefined) {
      await pref.put('loadStats', !!settings.loadStats);
    }
    if (settings.haptics !== undefined) {
      await pref.put('haptics', !!settings.haptics);
    }

    await pref.flush();
  }
}

这个 ArkTS 插件 SettingsBridge 使用 OpenHarmony 的 preferences 存储提供了一个轻量级的原生设置中心:loadNativeSettings() 负责从 PREF_NAME 指定的偏好文件中读取键值对,如果不存在就返回默认值;saveNativeSettings() 则将来自 Web 层的设置写入 Preferences 并 flush() 到磁盘。由于键名与 Web 侧的字段一一对应,序列化和反序列化都保持非常直接,减少了出错空间。

📝 总结

基本设置模块将喝茶记录应用从“硬编码配置”升级为“用户可配置应用”。通过 Web 表单与 ArkTS Preferences 的组合,语言、货币、默认首页、是否加载统计以及是否启用震动反馈等关键行为都可以由用户自行选择并长期保存。Cordova 在这里扮演了桥梁角色:一端是 HTML/CSS/JavaScript 构建的设置界面,另一端则是 OpenHarmony 的持久化能力与系统特性。未来如果需要扩展更多设置项(例如主题色、图表引擎选择、数据自动同步开关),只需在现有表单与 SettingsBridge 的基础上按相同模式扩展即可,整个架构已经为此做好了准备。

Logo

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

更多推荐