1.学习目标

完成本章学习后,你应当能够:

  1. 说出 HarmonyOS NEXT 的基本定位、核心特性和适用场景。
  2. 理解“分布式能力”“一次开发、多端部署”“原生精致体验”等概念。
  3. 按照要求安装和配置 DevEco Studio、HarmonyOS SDK、Node.js 与 OHPM。
  4. 解释 SDK、包管理器、编译器、模拟器和真机调试之间的关系。
  5. 使用 Empty Ability 模板创建一个简单的 HarmonyOS NEXT 工程。
  6. 识别工程中的入口页面、资源目录和配置文件。
  7. 使用 ArkTS 声明式 UI 编写简单页面。
  8. 理解元服务与普通应用的区别,以及元服务卡片的基本组成。
  9. 创建一个能够添加到桌面的元服务卡片,并完成基础动态刷新。
  10. 使用日志、预览器、模拟器和真机进行调试。
  11. 对常见安装失败、编译失败、卡片不显示等问题进行排查。
  12. 在坚持自主创新和遵守职业道德的前提下,形成规范、可靠、安全的开发习惯。

2.HarmonyOS NEXT 基础概念和特性

2.1 HarmonyOS NEXT 是什么

HarmonyOS NEXT 是面向新一代智能终端和全场景设备的操作系统形态。根据本章课程定位,它强调:
• 以自主研发的鸿蒙内核和系统能力为基础;
• 面向原生应用与元服务生态;
• 通过分布式架构连接不同设备;
• 支持在多种终端上提供一致、连续的服务体验;
• 通过统一开发工具和框架降低跨设备开发成本。
课程材料将 HarmonyOS NEXT 概括为“纯血鸿蒙”,并强调其不再以兼容安卓应用作为核心开发路径。学习时要注意:具体设备能力、API 可用范围、兼容策略和工具界面可能随系统与 SDK 版本变化,应以当前项目使用的官方文档和 SDK 实际能力为准。

2.1.1 操作系统与应用框架的关系

可以把一个操作系统理解为应用运行的基础平台:
硬件设备


操作系统内核与系统服务


应用框架与开发接口


应用、元服务、卡片和其他软件
开发者通常不直接操作硬件寄存器,而是调用系统提供的 API:
• 界面与窗口能力;
• 网络与数据访问能力;
• 文件与数据库能力;
• 设备传感器能力;
• 分布式协同能力;
• 通知、卡片和后台任务能力。

2.1.2 为什么需要新的应用形态

传统移动应用通常需要用户:

  1. 找到应用图标;
  2. 点击图标;
  3. 等待应用启动;
  4. 进入页面后查找目标功能。
    而元服务更强调:
    • 免安装或轻量触达;
    • 从桌面卡片、搜索、服务入口等位置直接访问;
    • 只呈现当前任务所需要的信息;
    • 即点即用,减少用户操作路径。
    因此,元服务适合天气、设备状态、订单进度、出行信息、快捷控制等“高频、轻量、信息明确”的场景。

2.2 HarmonyOS NEXT 的核心特性

2.2.1 全场景分布式架构

“全场景分布式”强调不同设备之间可以协同提供服务。设备不再只是各自独立运行应用,而是可以根据场景共同完成任务。
示意:
手机 ─────┐
平板 ─────┼── 分布式能力 ── 统一服务体验
手表 ─────┤
大屏 ─────┘
可能的协同方式包括:
• 手机发起任务,大屏展示结果;
• 手机采集数据,平板进行编辑;
• 设备状态在多个终端同步显示;
• 服务在更适合的设备上继续运行或呈现。
在农业场景中,可以设想:
田间传感器 → 网关/手机 → 元服务卡片 → 用户查看设备状态
卡片并不一定承载全部业务,而是将重要信息以更短路径展示给用户。

2.2.2 一次开发、多端部署

课程材料强调“一次开发,多端部署”。这并不意味着所有代码在所有设备上完全不需要调整,而是指:
• 通过统一的开发语言和 UI 框架复用大部分业务逻辑;
• 根据不同设备的屏幕、输入方式和资源能力进行适配;
• 将设备差异集中在配置、布局和能力调用层;
• 减少为每种设备重复编写完整应用的工作量。
开发时应区分:
在这里插入图片描述

2.2.3 原生精致体验

原生精致体验不仅是界面“好看”,还包括:
• 页面响应及时;
• 动画和反馈自然;
• 控件符合系统交互习惯;
• 字体、颜色和间距具有一致性;
• 在不同屏幕尺寸上保持可读性;
• 弱网、断网和加载失败时有明确提示;
• 权限、隐私和数据使用过程透明。
对于卡片来说,精致体验还包括:
• 一眼看懂核心信息;
• 信息层级清楚;
• 文字不过长;
• 数据更新时间明确;
• 点击区域足够大;
• 没有无意义的装饰和复杂操作。

2.2.4 原生开发语言与声明式 UI

HarmonyOS NEXT 工程常使用 ArkTS 进行开发。ArkTS 在 TypeScript 基础上结合了面向鸿蒙应用开发的类型约束和运行环境特性。
声明式 UI 的核心思想是:
状态数据 → UI 描述 → 系统根据状态构建界面
与命令式操作“找到控件、修改控件属性”相比,声明式写法更关注“在某种状态下界面应该是什么样子”。
概念示例:

@Entry
@Component
struct HelloPage {
  @State message: string = 'Hello HarmonyOS NEXT';

  build() {
    Column() {
      Text(this.message)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      Button('更新文字')
        .onClick(() => {
          this.message = '欢迎学习元服务开发';
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

点击按钮修改 message 后,页面会根据状态变化重新呈现。

2.3 “纯鸿蒙”概念的学习提示

课程材料使用“纯血鸿蒙”描述 HarmonyOS NEXT 的发展方向。作为学生,需要从以下角度理解:

  1. 关注鸿蒙原生 API、ArkTS、声明式 UI 和元服务能力。
  2. 不能简单把安卓项目的代码、目录和依赖直接复制到鸿蒙工程。
  3. 不同系统版本、设备型号和 SDK 版本可能存在 API 差异。
  4. 迁移旧项目时要重新检查权限、生命周期、页面路由和依赖。
  5. 应优先使用官方工具链和官方文档中明确支持的能力。
    学习中不要把概念口号当成技术细节。真正的开发能力来自:
    • 能否创建工程;
    • 能否正确配置 SDK;
    • 能否写出可编译的 ArkTS;
    • 能否在模拟器或真机运行;
    • 能否处理异常和版本差异;
    • 能否完成实际的用户任务。

3.DevEco Studio 开发环境安装

3.1 DevEco Studio 的作用

DevEco Studio 是 HarmonyOS 应用开发使用的官方集成开发环境(IDE)。它通常提供:
• 工程创建向导;
• ArkTS 代码编辑;
• UI 预览;
• 代码补全和重构;
• 编译和构建;
• 模拟器管理;
• 真机调试;
• 日志查看;
• SDK 和设备管理;
• 签名、打包和发布前检查。
可以把 IDE 理解为开发过程中的工作台:
代码编辑 ─┐
资源管理 ─┤
工程构建 ─┼── DevEco Studio
模拟调试 ─┤
日志排错 ─┘
IDE 并不会代替开发者完成需求分析和类型设计。它主要帮助你更高效地编写、构建、运行和调试项目。

3.2 安装前检查

硬件与系统
安装前应检查:
• 操作系统版本是否满足当前 DevEco Studio 要求;
• CPU、内存和磁盘空间是否充足;
• 是否拥有安装软件和配置环境变量的权限;
• 是否已经安装其他版本并可能产生路径冲突;
• 防火墙或安全软件是否会阻止 SDK 下载;
• 是否能够访问官方软件下载和依赖仓库。
模拟器通常比普通文本编辑器占用更多内存和磁盘空间。如果计算机配置有限,可以优先使用预览器或连接实体设备调试。
软件准备
本章涉及的主要软件:
在这里插入图片描述
具体版本应以当前课程环境和官方要求为准,不要直接套用过期教程中的版本号。

3.3 安装 DevEco Studio

建议按照以下顺序操作:

  1. 从官方渠道下载与当前系统匹配的 DevEco Studio 安装包。
  2. 运行安装程序,阅读许可协议和安装说明。
  3. 选择安装目录,尽量使用路径简单、无特殊字符的目录。
  4. 根据向导安装必要组件。
  5. 首次启动时设置 SDK 存储位置。
  6. 在 SDK Manager 中安装课程需要的 SDK、工具和模拟器组件。
  7. 根据提示配置 Node.js、OHPM 和其他依赖。
  8. 创建测试工程并执行一次编译,确认环境可用。

3.3.1 路径命名建议

建议:

D:\HarmonyOS\DevEcoStudio
D:\HarmonyOS\Sdk
D:\Projects\MetaServiceDemo

尽量避免:
C:\我的项目\鸿蒙测试项目\最终版本\新建文件夹
路径过长、包含特殊符号、中文字符或多层嵌套,可能导致某些工具无法正常工作。不是所有环境都存在此问题,但使用简洁路径更容易排查。

3.4 配置 Node.js

Node.js 主要用于运行前端和工程工具链。检查是否安装成功:
node --version
npm --version
如果命令无法识别,可能原因包括:
• Node.js 尚未安装;
• 安装后终端未重新打开;
• PATH 环境变量没有更新;
• 系统中同时存在多个 Node.js 版本;
• 使用了错误的终端或用户权限。
建议在安装后重新打开 DevEco Studio 和终端,再检查版本。

3.5 配置 OHPM

OHPM 是用于管理鸿蒙项目依赖的包管理工具。常见用途包括:
• 安装项目依赖;
• 更新依赖版本;
• 管理依赖锁定信息;
• 执行项目构建所需的包操作。
使用包管理器时要注意:

  1. 依赖来源应可信。
  2. 不要随意安装来源不明的包。
  3. 记录依赖版本,保证团队环境一致。
  4. 遇到安装失败时先查看网络、权限、镜像和路径。
  5. 不要为了“能编译”而关闭安全检查。

3.6 安装 HarmonyOS SDK

SDK 是开发时使用的工具和 API 集合。安装时通常需要关注:
• SDK API 版本;
• SDK Platform;
• Build Tools;
• Previewer 或模拟器组件;
• 设备运行所需的系统镜像;
• 命令行工具和调试工具。
SDK 版本选择原则
• 课程项目优先使用老师或项目规定的版本。
• 没有明确要求时,使用当前稳定版本。
• 不要在同一项目中频繁切换 SDK 版本。
• 升级 SDK 前先备份或提交代码。
• 如果 API 在新旧版本之间变化,应查看迁移说明。

3.7 环境变量与路径

环境变量用于让系统或工具找到需要的程序和目录。开发环境中常见的路径类型:
Node.js 可执行文件路径
OHPM 可执行文件路径
HarmonyOS SDK 根目录
构建工具目录
模拟器或设备工具目录
排查路径问题时,建议按以下顺序:

  1. 记录 DevEco Studio 中配置的 SDK 路径。
  2. 检查该目录是否真实存在。
  3. 检查目录下是否包含预期的工具和平台文件。
  4. 在终端执行版本命令。
  5. 重新启动终端和 IDE。
  6. 使用一个空工程执行构建验证。
    不要把环境变量中的路径复制到不熟悉的系统目录中修改。配置前先记下原值,避免误删其他软件的 PATH。

3.8 环境安装验收清单

完成环境安装后,至少确认:
• [ ] DevEco Studio 能够正常启动。
• [ ] SDK Manager 能够打开。
• [ ] 课程要求的 SDK 已安装。
• [ ] Node.js 版本命令可以执行。
• [ ] OHPM 或项目依赖工具可以执行。
• [ ] 可以创建一个空工程。
• [ ] 空工程可以完成同步或依赖解析。
• [ ] 空工程可以编译。
• [ ] 可以打开预览器或连接设备。
• [ ] 能够看到运行日志。
• [ ] 工程路径没有明显的权限或字符问题。

4.创建第一个 HarmonyOS NEXT 工程

4.1 什么是工程模板

工程模板是 IDE 根据开发场景生成的项目骨架。模板通常会预先创建:
• 目录结构;
• 入口文件;
• 配置文件;
• 资源目录;
• 构建脚本;
• 最小可运行页面。
本章使用 Empty Ability 模板。它适合从一个最小项目开始学习,避免初学阶段被复杂业务代码干扰。

4.2 创建工程的基本步骤

  1. 启动 DevEco Studio。
  2. 选择 Create Project。
  3. 选择适合当前设备和课程要求的应用模板。
  4. 选择 Empty Ability。
  5. 填写项目名称。
  6. 设置保存位置。
  7. 设置包名或 Bundle 名称。
  8. 选择 SDK 或 API 版本。
  9. 确认项目路径和模块信息。
  10. 点击创建,等待 IDE 生成工程。
  11. 等待依赖同步和索引建立完成。
  12. 查看入口页面并运行默认示例。

4.2.1 项目名称

项目名称用于开发阶段识别工程,例如:
MetaServiceHello
AgricultureDeviceCard
HarmonyFirstApp
建议:
• 使用英文、数字和下划线;
• 不使用空格和特殊符号;
• 名称能够体现项目用途;
• 不要把版本号、临时测试词随意写入正式项目名称。

4.2.2 包名

包名用于标识应用或模块,通常要求具有唯一性。常见结构类似:
com.example.metaserivce
com.school.agriculture
实际项目应按学校、组织或企业命名规范设置。创建后不要随意修改包名,因为它可能影响:
• 应用身份;
• 签名;
• 数据目录;
• 发布配置;
• 卡片和元服务关联关系。

4.2.3 SDK 路径

SDK 路径必须指向已经安装并可用的 SDK 目录,而不是随意选择一个空文件夹。路径错误会导致:
• 找不到 API;
• 编译工具缺失;
• 预览器无法启动;
• 设备运行失败;
• 工程同步报错。

4.3 工程目录的基本认识

不同 DevEco Studio 和 SDK 版本生成的目录可能略有差异,但通常可以从以下类别理解:
项目根目录
├── AppScope/ # 应用级资源或配置
├── entry/ # 入口模块
│ ├── src/main/ets/ # ArkTS 源码
│ ├── src/main/resources/ # 图片、字符串等资源
│ └── module.json5 # 模块配置
├── oh_modules/ # 依赖目录(实际名称可能因版本不同)
├── hvigorfile.ts # 构建配置或脚本
├── build-profile.json5 # 构建配置
└── oh-package.json5 # 依赖和包配置

4.3.1 ets 源码目录

这里通常存放:
• 页面;
• 组件;
• 状态管理;
• 工具类;
• 数据模型;
• 服务调用。
建议按职责组织:
ets/
├── pages/
├── components/
├── model/
├── service/
└── utils/
小项目可以从简单结构开始,随着代码增长再拆分模块。

4.3.2 resources 资源目录

资源目录通常用于放置:
• 图片;
• 字符串;
• 颜色;
• 样式;
• 多语言资源;
• 设备适配资源。
不要把所有文字硬编码在页面中。需要多语言、统一修改或无障碍适配时,应使用资源文件。

4.3.3 模块配置文件

模块配置用于描述:
• 模块名称;
• 页面入口;
• 能力声明;
• 权限;
• 组件;
• 卡片或元服务相关信息;
• 编译和运行所需的配置。
修改配置前应先了解字段含义。配置文件中一个拼写错误,可能导致工程无法同步或安装。

4.4 编写第一个页面

下面是一个用于理解声明式 UI 的简化示例:

@Entry
@Component
struct Index {
  @State title: string = '我的第一个鸿蒙应用';
  @State count: number = 0;

  build() {
    Column({ space: 16 }) {
      Text(this.title)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      Text(`点击次数:${this.count}`)
        .fontSize(18)

      Button('点击我')
        .onClick(() => {
          this.count += 1;
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

4.4.1 代码分析

在这里插入图片描述

4.4.2 状态驱动界面

当 count 发生变化时:
this.count += 1;
页面中的:
Text(点击次数:${this.count})
会显示最新值。可以把它理解为:
用户点击

状态 count 改变

框架检测到状态变化

相关 UI 重新构建

页面显示新内容

4.5 编译、运行与调试

  1. 编译
    编译的目标是检查代码并生成可以运行的应用产物。编译失败时,先看第一条错误,不要只看最后一条连锁错误。
    运行
    运行可以选择:
    • 预览器;
    • 模拟器;
    • 已连接的真机。
  2. 调试
    调试包括:
    • 设置断点;
    • 查看变量值;
    • 查看调用栈;
    • 检查日志;
    • 观察页面状态;
    • 验证点击和页面跳转。
  3. 运行验收
    首个工程至少应验证:
    • 页面能正常打开;
    • 文本显示完整;
    • 按钮可点击;
    • 点击后状态发生变化;
    • 没有明显的红色错误日志;
    • 多次点击不会造成页面崩溃。

5.元服务与元服务卡片

5.1 什么是元服务

元服务是一种轻量、便捷、强调即时触达的服务形态。它不要求用户先完整安装一个传统应用再寻找功能,而是可以从系统提供的入口快速使用服务。
典型特征:
• 免安装或轻量使用;
• 服务入口丰富;
• 任务目标明确;
• 页面和交互相对精简;
• 适合信息查询和快捷操作;
• 可以通过卡片在桌面持续外显关键信息。

5.1.1 元服务与普通应用的对比

在这里插入图片描述
元服务并不是“把普通应用页面缩小”,而是要重新思考用户在最短时间内需要什么。

5.2 什么是元服务卡片

元服务卡片是可以放置在桌面或系统相关入口中的信息展示和快捷交互单元。它通常包括:
• 卡片标题;
• 关键数据;
• 更新时间;
• 简单状态;
• 点击后执行的动作;
• 刷新机制;
• 与元服务或应用的关联配置。
例如农业设备卡片可以展示:
智慧农场
在线设备:18
离线设备:2
维护设备:1
最近更新:08:30
用户点击卡片后,可以进入设备详情或元服务页面。

5.3 卡片设计原则

信息优先
卡片空间有限,优先展示:

  1. 用户最关心的数字;
  2. 当前异常或风险;
  3. 数据更新时间;
  4. 能够继续操作的入口。
    不要在卡片中堆积所有字段。
    层级清晰
    建议使用如下层级:
    卡片标题
    ├── 主要指标
    ├── 状态提示
    └── 更新时间/操作入口
    适配不同尺寸
    同一个卡片可能存在不同尺寸或布局。设计时要考虑:
    • 小尺寸只保留核心指标;
    • 大尺寸展示更多摘要;
    • 长文本自动截断;
    • 数字和状态保持可读;
    • 不依赖固定像素宽度;
    • 在浅色和深色环境下具有足够对比度。
    数据时效明确
    显示数据时应让用户知道:
    • 数据来自什么时候;
    • 是否正在刷新;
    • 刷新是否失败;
    • 数据是否可能过期。

6.创建第一个元服务卡片

下面示例用于讲解结构和思路。不同版本的 DevEco Studio、SDK 和卡片 API 可能存在名称或配置差异,实际编码时应以当前工程模板生成的接口为准。

6.1 实现流程

创建卡片可以拆成以下步骤:
明确卡片场景

设计卡片信息结构

创建卡片相关模块或组件

编写 ArkTS UI

准备卡片数据

配置刷新机制

配置卡片入口和能力

编译运行

添加到桌面验证

6.2 设计农业设备卡片数据

先定义数据结构,再编写界面:

interface EquipmentSummary {
  onlineCount: number;
  offlineCount: number;
  maintenanceCount: number;
  updatedAt: string;
}
准备初始数据:
const defaultSummary: EquipmentSummary = {
  onlineCount: 18,
  offlineCount: 2,
  maintenanceCount: 1,
  updatedAt: '08:30'
};

使用接口的好处:
• 字段名称清楚;
• 编辑器可以提示属性;
• 少写字段时会得到编译提醒;
• 后续扩展数据更容易;
• 卡片 UI 和数据来源之间有明确契约。

6.3 编写卡片界面

概念示例:

@Component
struct EquipmentCardContent {
  @Prop summary: EquipmentSummary;

  build() {
    Column({ space: 8 }) {
      Text('智慧农场')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)

      Row({ space: 12 }) {
        Column() {
          Text(`${this.summary.onlineCount}`)
            .fontSize(22)
            .fontWeight(FontWeight.Bold)
          Text('在线')
            .fontSize(12)
        }

        Column() {
          Text(`${this.summary.offlineCount}`)
            .fontSize(22)
            .fontWeight(FontWeight.Bold)
          Text('离线')
            .fontSize(12)
        }

        Column() {
          Text(`${this.summary.maintenanceCount}`)
            .fontSize(22)
            .fontWeight(FontWeight.Bold)
          Text('维护')
            .fontSize(12)
        }
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceAround)

      Text(`更新于 ${this.summary.updatedAt}`)
        .fontSize(11)
        .opacity(0.65)
    }
    .padding(16)
    .width('100%')
}

该示例体现了卡片的三个层次:

  1. 标题;
  2. 核心指标;
  3. 更新时间。
    @Prop 表示组件接收外部传入的数据。卡片的数据更新时,内容组件可以根据新数据重新构建。

6.4 卡片状态与刷新

卡片需要考虑至少三种状态:

type CardState =
  | { kind: 'loading' }
  | { kind: 'success'; summary: EquipmentSummary }
  | { kind: 'error'; message: string };
状态渲染思路:
@Component
struct CardStateView {
  @Prop state: CardState;

  build() {
    Column() {
      if (this.state.kind === 'loading') {
        Text('正在更新设备数据……')
      } else if (this.state.kind === 'success') {
        EquipmentCardContent({ summary: this.state.summary })
      } else {
        Text(this.state.message)
          .fontColor('#B42318')
      }
    }
    .padding(16)
  }
}

刷新机制的基本思想
动态刷新不是“每秒无条件请求一次”。设计刷新机制时,应考虑:
• 什么时候首次加载;
• 什么时候用户主动刷新;
• 系统允许的刷新频率;
• 网络是否可用;
• 数据是否发生变化;
• 后台任务是否受到限制;
• 失败后是否需要重试;
• 如何显示上次成功更新时间。
一种通用流程:
触发刷新

检查是否正在刷新
├── 是:忽略重复请求
└── 否:进入 loading

获取或计算数据
├── 成功 → 更新数据和时间
└── 失败 → 显示错误或保留旧数据
伪代码:

async function refreshSummary(): Promise<EquipmentSummary> {
  const response = await fetchSummaryFromService();

  if (!response.ok) {
    throw new Error('设备数据获取失败');
  }

  const data: unknown = await response.json();

  if (!isEquipmentSummary(data)) {
    throw new Error('设备数据格式不正确');
  }

  return data;
}
数据校验函数:
function isEquipmentSummary(
  value: unknown
): value is EquipmentSummary {
  if (typeof value !== 'object' || value === null) {
    return false;
  }

  const item = value as Record<string, unknown>;

  return (
    typeof item.onlineCount === 'number' &&
    typeof item.offlineCount === 'number' &&
    typeof item.maintenanceCount === 'number' &&
    typeof item.updatedAt === 'string'
  );
}

还可以增加业务校验:

function isNonNegativeInteger(value: number): boolean {
  return Number.isInteger(value) && value >= 0;
}

如果设备数量可能出现负数或小数,应拒绝该数据,而不是直接展示。

6.5 卡片刷新策略

常见刷新策略:
在这里插入图片描述
课程练习阶段可以先实现“首次加载 + 手动刷新”,再研究定时或事件驱动刷新。

6.6 卡片点击行为

卡片点击后可以:
• 打开元服务详情;
• 跳转到设备列表;
• 打开异常设备列表;
• 执行一个安全的快捷操作。
不要让点击行为不可预测。建议:
点击卡片主体 → 查看设备摘要或设备列表
点击明确按钮 → 执行对应操作
涉及远程控制时,必须增加:
• 权限验证;
• 设备在线检查;
• 二次确认;
• 操作结果反馈;
• 失败和超时处理;
• 操作日志。

6.7 将卡片添加到桌面

完成卡片代码和配置后,通常需要:

  1. 编译并安装工程;
  2. 启动应用或元服务;
  3. 按系统方式进入桌面卡片添加入口;
  4. 找到对应的元服务或卡片名称;
  5. 选择卡片尺寸;
  6. 添加到桌面;
  7. 检查数据显示;
  8. 触发刷新或等待系统刷新;
  9. 点击卡片验证跳转;
  10. 修改数据后再次验证显示是否更新。
    桌面验收内容
    • [ ] 卡片可以在添加入口中找到。
    • [ ] 卡片标题和图标正确。
    • [ ] 小尺寸下主要数据不被截断。
    • [ ] 卡片首次加载有合理反馈。
    • [ ] 数据刷新后内容发生变化。
    • [ ] 网络失败时有可理解的提示。
    • [ ] 卡片点击行为正确。
    • [ ] 返回或再次打开后状态正常。
    • [ ] 删除和重新添加卡片后仍能正常工作。

7.卡片页面的布局与交互设计

7.1 常用布局组件

在声明式 UI 中,常见布局思路包括:
Column:垂直排列
Row:水平排列
Stack:层叠布局
Grid:网格布局
List:列表布局
Scroll:滚动容器
农业设备摘要卡片可以采用:
Column
├── 标题
├── Row
│ ├── 在线数量
│ ├── 离线数量
│ └── 维护数量
└── 更新时间

7.2 间距和信息密度

卡片不是越满越好。应控制:
• 标题与指标之间的间距;
• 指标之间的间距;
• 数字和单位的距离;
• 卡片内边距;
• 文本行高;
• 小屏幕下的最小可读字号。
建议先用少量信息完成可用版本,再根据真实设备预览调整。

7.3 状态颜色不能只靠颜色

在线、离线、维护状态可以使用颜色,但不要只用颜色区分:
在线 ● 在线
离线 ● 离线
维护 ● 维护中
同时配合:
• 文字;
• 图标;
• 数值;
• 更新时间;
• 语义化标签。
这样在色觉差异、低亮度或无障碍场景下仍然可理解。

7.4 长文本和异常数字

卡片中可能出现:
• 设备名称很长;
• 离线设备数量为三位数;
• 更新时间格式异常;
• 网络异常时错误消息很长。
处理建议:

function shortenText(text: string, maxLength: number): string {
  return text.length <= maxLength
    ? text
    : `${text.slice(0, maxLength - 1)}…`;
}

对于数字,提前设计空间:
在线:999+
不要让超长数字破坏整个卡片布局。

8.调试方法与常见问题

8.1 工程创建失败

现象
• Create Project 后长时间无响应;
• 模板列表为空;
• SDK 选项不可用;
• 创建按钮无法点击。
排查

  1. 检查 DevEco Studio 是否完整安装。
  2. 检查 SDK Manager 是否安装课程所需组件。
  3. 检查项目路径是否有写入权限。
  4. 检查路径是否过长或包含特殊字符。
  5. 查看 IDE 的错误日志。
  6. 关闭后重新启动 IDE。
  7. 使用一个简单名称创建最小工程。

8.2 依赖同步失败

可能原因
• 网络访问失败;
• OHPM 配置错误;
• 依赖版本不存在;
• 本地缓存损坏;
• Node.js 或包管理器版本不匹配。
建议处理
记录完整错误

确认网络和仓库地址

确认 Node.js/OHPM 可执行

确认项目配置和依赖版本

重新同步

仍失败时更换到课程规定环境
不要直接删除整个工作区或系统目录。先备份项目,再清理明确的构建缓存。

8.3 编译报错

优先关注:
• 第一条真正的错误;
• 错误所在文件和行号;
• 类型不匹配;
• 装饰器或组件名称拼写;
• 缺少导入;
• 配置文件格式;
• 资源名称和路径。
常见错误示例:
const count: number = ‘10’;
修复:
const count: number = 10;
或者正确转换:
const count = Number(‘10’);

8.4 页面无法显示

排查顺序:

  1. 页面是否标记为入口页面。
  2. build() 是否返回了有效的组件结构。
  3. 组件名称是否拼写正确。
  4. 是否存在运行时异常。
  5. 是否使用了未初始化的数据。
  6. 是否把不支持的 API 放到当前目标设备上。
  7. 查看预览器、模拟器和真机日志。

8.5 卡片无法添加到桌面

可能原因:
• 卡片配置未生效;
• 工程未正确安装;
• 元服务或卡片入口声明不完整;
• 卡片名称或资源缺失;
• 目标设备不支持当前卡片能力;
• 使用的 SDK 版本和设备系统不匹配;
• 旧版本卡片缓存尚未刷新。
建议:
• 先确认普通应用工程能够运行;
• 再确认卡片最小版本能够显示静态文字;
• 最后逐步加入动态数据和点击行为;
• 修改配置后重新编译安装;
• 删除旧卡片后重新添加;
• 保留完整日志和配置截图,便于定位。

8.6 卡片数据不更新

排查以下问题:
• 刷新函数是否被真正调用;
• 是否存在重复刷新锁;
• 新数据是否成功获取;
• 状态变量是否更新;
• 卡片 UI 是否读取了旧对象;
• 系统刷新周期是否受到限制;
• 是否使用了缓存数据;
• 更新时间是否变化。
可以先用本地递增数字验证刷新链路:

let refreshCount = 0;

function getMockSummary(): EquipmentSummary {
  refreshCount += 1;

  return {
    onlineCount: 18 + refreshCount,
    offlineCount: 2,
    maintenanceCount: 1,
    updatedAt: `第 ${refreshCount} 次刷新`
  };
}

如果本地模拟数据能够更新,说明 UI 和状态链路基本可用,再继续排查网络或系统刷新机制。

8.7 真机调试注意事项

真机调试前要确认:
• 设备系统版本满足要求;
• 开发者选项和调试授权已开启;
• 数据线或无线调试连接稳定;
• 设备已被 IDE 识别;
• 应用签名和安装权限正常;
• 设备上的旧版本应用不会干扰测试。
涉及个人设备和真实农业设备时,应注意数据隐私、权限边界和操作风险。

9.从 Hello World 到元服务卡片的分层实现

推荐采用“先静态、再动态、后交互”的开发顺序。
第一步:静态卡片
先只显示固定文字:
智慧农场
在线设备:18
离线设备:2
目标:验证工程、卡片配置和桌面添加流程。
第二步:本地动态数据
使用本地状态或模拟函数:
刷新一次 → 在线数量增加 1
目标:验证状态变化和 UI 更新。
第三步:服务数据
从接口或本地服务获取数据:
请求开始 → loading
请求成功 → 显示统计
请求失败 → 显示错误
目标:验证异步流程和异常处理。
第四步:卡片点击
点击卡片跳转到元服务详情页或设备列表。
目标:验证入口关联和页面路由。
第五步:适配和优化
增加:
• 不同卡片尺寸;
• 深色模式;
• 空数据状态;
• 弱网提示;
• 权限处理;
• 日志和测试。
这种分层方式可以把复杂问题拆成多个小问题,避免一次性引入过多变量。

Logo

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

更多推荐