【OpenHarmony/HarmonyOs 】从化学学习 App 出发:近场快传、实况窗与全场景智慧学习方案

本文基于「化学视界」这个 HarmonyOS 项目展开。当前项目已经具备离线题库、元素周期表、方程式、收藏、错题、成就、学习统计、平板适配等能力。本文重点不是说这些能力已经全部接入系统级近场快传和实况窗,而是说明:在现有项目结构上,如何自然扩展到近场分享、实况窗提醒和全场景智慧学习。🚀

一、项目为什么适合做“全场景学习”?

化学学习有一个明显特点:学习发生在多个碎片场景里。

  • 上课时快速查一个元素。
  • 做题时查看方程式现象。
  • 晚上复习错题。
  • 通勤时刷每日一题。
  • 平板上横屏看周期表。
  • 和同学分享某个元素、方程式或知识点。

这些场景天然适合鸿蒙生态的全场景能力:手机负责随手查,平板负责大屏学习,分享能力负责资料流转,实况窗负责把“正在进行的挑战”留在系统可见位置。

当前项目已经有一些基础:

  • 📱 deviceTypes 支持 phonetablet
  • 🧩 页面路由清晰,详情页可通过参数打开。
  • ⭐ 收藏、错题、成就数据本地保存。
  • ⏱️ 限时挑战有明确的倒计时状态。
  • 📤 元素详情页已经预留分享按钮。
  • ☁️ 配置了备份扩展能力。

模块配置如下:

{
  "deviceTypes": [
    "phone",
    "tablet"
  ],
  "extensionAbilities": [
    {
      "name": "EntryBackupAbility",
      "type": "backup",
      "exported": false
    }
  ]
}

这为后续的“全场景智慧生活”扩展打好了底。

二、近场快传:学习内容最小单元化

近场快传的核心不是“传整个 App”,而是传一个清晰、轻量、可被接收方理解的学习对象。

在化学学习 App 里,适合作为分享单元的内容有:

  • 一个元素:例如 H、Na、Fe。
  • 一个方程式:例如铁与氧气反应。
  • 一个知识点:例如质量守恒定律。
  • 一组错题:例如今天答错的 5 道题。
  • 一次挑战结果:例如 10 题正确 8 题。

项目的元素详情页已经有分享按钮:

Row() {
  Image($r('app.media.icon_share'))
    .width(20)
    .height(20)
    .fillColor($r('app.color.text_tab_inactive'))
}
.width(40)
.height(40)
.borderRadius(20)
.backgroundColor($r('app.color.background_color'))
.scale({ x: this.shareButtonScale, y: this.shareButtonScale })

目前这只是一个 UI 入口,后续可以把它接成系统分享、近场快传或自定义 Want 跳转。建议先定义统一的分享数据结构:

interface SharePayload {
  type: 'element' | 'equation' | 'knowledge' | 'quizResult';
  id: string;
  title: string;
  summary: string;
  deepLink: string;
}

比如元素详情页可以生成:

const payload: SharePayload = {
  type: 'element',
  id: String(this.elementLocal.number),
  title: `${this.elementLocal.name} (${this.elementLocal.symbol})`,
  summary: `原子序数 ${this.elementLocal.number},原子量 ${this.elementLocal.atomicMass}`,
  deepLink: `huaxue://element/${this.elementLocal.number}`
};

这样不管是系统分享、近场快传,还是未来接入碰一碰、跨设备流转,都可以复用同一份数据。

三、详情页路由:让分享内容可以被精准打开

当前项目详情页通过 router.getParams() 接收参数,例如元素详情:

let params = router.getParams() as Record<string, number>;
if (params && params.elementNumber) {
  let el = getElementByNumber(params.elementNumber);
  if (el) {
    this.element = el;
    this.elementLocal = el;
    this.isFavorite = isFavorited('element', String(el.number));
  }
}

这意味着只要分享内容里带上 elementNumber,接收方就能直接打开对应元素详情页,而不是从首页重新搜索。

推荐的扩展方式:

  1. 分享时生成 type + id
  2. 接收方解析 type
  3. 根据类型跳转到对应页面。
  4. 页面使用原有参数加载内容。

伪代码如下:

function openSharedPayload(payload: SharePayload) {
  if (payload.type === 'element') {
    router.pushUrl({
      url: 'pages/periodic/ElementDetail',
      params: { elementNumber: Number(payload.id) }
    });
  }

  if (payload.type === 'equation') {
    router.pushUrl({
      url: 'pages/equations/EquationDetail',
      params: { equationId: Number(payload.id) }
    });
  }
}

这一步是近场快传体验的关键:传输只是入口,真正影响体验的是“对方打开后是否一步到位”。

四、实况窗:最适合接入限时挑战

在这个项目里,最适合接入实况窗的模块是“限时挑战”。因为它具备典型的实时状态:

  • 当前正在答第几题。
  • 剩余时间。
  • 正确数和错误数。
  • 挑战是否结束。

TimeChallengeView 中已经有这些状态:

@State private challengeState: string = 'setup';
@State private questionCount: number = 10;
@State private timePerQuestion: number = 60;
@State private currentIndex: number = 0;
@State private remainingSeconds: number = 0;
@State private correctCount: number = 0;
@State private wrongCount: number = 0;

这几项可以抽象成实况窗展示模型:

interface ChallengeLiveState {
  title: string;
  progressText: string;
  remainingText: string;
  scoreText: string;
}

生成状态时可以这样写:

const liveState: ChallengeLiveState = {
  title: '化学限时挑战',
  progressText: `${this.currentIndex + 1}/${this.questionCount}`,
  remainingText: this.remainingSeconds > 0
    ? `${this.remainingSeconds}s`
    : '不限时',
  scoreText: `对 ${this.correctCount} · 错 ${this.wrongCount}`
};

接入实况窗后,用户即使暂时切到其他应用,也能看到挑战还剩多久。对学习 App 来说,这种提醒不是打扰,而是帮助用户维持学习节奏。⏱️

五、全场景智慧生活:手机、平板、备份恢复

当前项目已经支持手机和平板:

"deviceTypes": [
  "phone",
  "tablet"
]

页面里也做了平板断点判断:

const displayClass: display.Display = display.getDefaultDisplaySync();
const density = displayClass.densityDPI;
const screenWidthVp = density > 0
  ? displayClass.width / density * 160
  : 360;

this.isTabletMode = screenWidthVp >= 600;

这让同一套代码能在不同设备上呈现不同密度:

  • 手机:单列、轻量、适合随手查。
  • 平板:更大字号、更高 TabBar、更宽详情页,适合系统学习。
  • 横屏:周期表这类 18 列信息可以展示得更完整。

此外,项目还配置了备份能力:

{
  "allowToBackupRestore": true
}

这对学习类 App 很重要。用户的收藏、错题、成就、学习天数都属于长期积累的数据,一旦换设备或重装,如果完全丢失,学习连续性会被打断。

六、收藏与错题:跨设备流转的核心数据

项目的收藏管理器用 AppStorage 存储数据,并通过版本号触发 UI 刷新:

function writeFavorites(items: FavoriteItem[]): void {
  AppStorage.setOrCreate(STORAGE_KEY, JSON.stringify(items));
  const version = (AppStorage.get<number>(STORAGE_VERSION_KEY) ?? 0) + 1;
  AppStorage.setOrCreate(STORAGE_VERSION_KEY, version);
}

错题集也采用轻量存储:

export function addWrongQuestionId(id: number): void {
  const ids = readIds();
  if (!ids.includes(id)) {
    ids.push(id);
    writeIds(ids);
  }
}

这些数据非常适合做跨设备同步或备份恢复:

  • 收藏:用户主动标记的长期兴趣。
  • 错题:用户短期学习弱点。
  • 成就:用户持续使用的激励系统。
  • 学习统计:可以生成个性化学习报告。

如果后续做全场景,可以把它们拆成多个数据域,而不是全部混在一个大 JSON 里。这样更方便做版本迁移和局部同步。

七、近场快传文章里的落地写法

如果你要把这个主题写成 CSDN 文章,不建议只写“鸿蒙支持近场快传”。更推荐按照下面逻辑展开:

  1. 先说明教育 App 的真实分享场景。
  2. 再说明项目中已有的分享入口和详情页参数路由。
  3. 然后定义统一的 SharePayload
  4. 最后扩展到系统分享、近场快传、跨设备打开。

这样文章会显得有项目基础,而不是纯概念。

可以这样总结:

近场快传不是简单传文本,而是把学习内容变成“可识别、可跳转、可复习”的结构化对象。

八、实况窗文章里的落地写法

实况窗不要什么都放,最适合展示“正在发生、状态会变化、用户关心结果”的内容。

在本项目中,限时挑战最合适:

  • 正在进行。
  • 有倒计时。
  • 有进度。
  • 有结果。
  • 用户切出 App 后仍然关心。

实况窗展示内容建议控制在三行以内:

  • 标题:化学限时挑战。
  • 进度:第 3/10 题。
  • 状态:剩余 42 秒,对 2 错 0。

复杂解析、题干、选项不适合放进实况窗。实况窗负责提醒和回流,完整答题仍然回到 App 内完成。

九、总结

「化学视界」当前虽然是一个离线学习工具,但它的模块结构很适合扩展到鸿蒙全场景:

  • 📤 元素、方程式、知识点可以做近场快传。
  • ⏱️ 限时挑战可以接入实况窗。
  • 📱 手机和平板可以共享同一套响应式页面。
  • ☁️ 收藏、错题、成就可以通过备份能力延续学习数据。
  • 🔗 路由参数可以让分享内容被精准打开。

所以这类项目写鸿蒙新特性文章时,不必强行追求“大而全”。只要从一个真实学习场景切入,把系统能力和项目结构连接起来,就能写出既有技术含量又有产品思考的内容。🌈

img

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐