
DevEco Code 在 MacOS 系统上的完整安装、配置与卸载全面使用指南
-
- 摘要
- 目录
- [一、DevEco Code 概述与 MacOS 适配](#一、DevEco Code 概述与 MacOS 适配)
-
- [1.1 什么是 DevEco Code](#1.1 什么是 DevEco Code)
- [1.2 MacOS 平台的独特优势](#1.2 MacOS 平台的独特优势)
- [1.3 Intel Mac 与 Apple Silicon Mac 的差异](#1.3 Intel Mac 与 Apple Silicon Mac 的差异)
- [1.4 DevEco Code 与 DevEco Studio、CodeGenie 的区别](#1.4 DevEco Code 与 DevEco Studio、CodeGenie 的区别)
- [1.5 核心能力总览](#1.5 核心能力总览)
- [1.6 适用场景与目标用户](#1.6 适用场景与目标用户)
- 二、环境准备与前置条件
-
- [2.1 MacOS 版本要求](#2.1 MacOS 版本要求)
- [2.2 硬件配置建议](#2.2 硬件配置建议)
- [2.3 必备软件清单](#2.3 必备软件清单)
- [2.4 华为开发者账号准备](#2.4 华为开发者账号准备)
- [2.5 Xcode Command Line Tools 安装](#2.5 Xcode Command Line Tools 安装)
- [三、安装 Homebrew 包管理器](#三、安装 Homebrew 包管理器)
-
- [3.1 Homebrew 简介](#3.1 Homebrew 简介)
- [3.2 安装 Homebrew](#3.2 安装 Homebrew)
- [3.3 Apple Silicon 上的路径差异](#3.3 Apple Silicon 上的路径差异)
- [3.4 配置 Homebrew 国内镜像](#3.4 配置 Homebrew 国内镜像)
- [3.5 Homebrew 常用命令速查](#3.5 Homebrew 常用命令速查)
- [四、安装 Node.js 与 npm 环境](#四、安装 Node.js 与 npm 环境)
-
- [4.1 方案一:通过 Homebrew 安装 Node.js](#4.1 方案一:通过 Homebrew 安装 Node.js)
- [4.2 方案二:通过 nvm 管理多版本 Node.js](#4.2 方案二:通过 nvm 管理多版本 Node.js)
- [4.3 方案三:通过 fnm 管理 Node.js(推荐)](#4.3 方案三:通过 fnm 管理 Node.js(推荐))
- [4.4 验证 Node.js 与 npm 安装](#4.4 验证 Node.js 与 npm 安装)
- [4.5 配置 npm 国内镜像源](#4.5 配置 npm 国内镜像源)
- [4.6 解决 MacOS 全局安装权限问题](#4.6 解决 MacOS 全局安装权限问题)
- [4.7 Shell 配置文件详解(zsh vs bash)](#4.7 Shell 配置文件详解(zsh vs bash))
- [五、安装 DevEco Code](#五、安装 DevEco Code)
-
- [5.1 npm 全局安装](#5.1 npm 全局安装)
- [5.2 安装过程全记录](#5.2 安装过程全记录)
- [5.3 验证安装成功](#5.3 验证安装成功)
- [5.4 Apple Silicon 特殊注意事项](#5.4 Apple Silicon 特殊注意事项)
- [5.5 安装失败常见原因与排查](#5.5 安装失败常见原因与排查)
- 六、首次启动与登录配置
-
- [6.1 终端选择与启动方式](#6.1 终端选择与启动方式)
- [6.2 数据库迁移与初始化](#6.2 数据库迁移与初始化)
- [6.3 华为开发者账号登录](#6.3 华为开发者账号登录)
- [6.4 隐私政策与使用条款](#6.4 隐私政策与使用条款)
- [6.5 登录状态管理与凭证安全](#6.5 登录状态管理与凭证安全)
- 七、模型配置与第三方模型接入
-
- [7.1 内置免费模型 GLM-5.1](#7.1 内置免费模型 GLM-5.1)
- [7.2 使用 /model 命令切换模型](#7.2 使用 /model 命令切换模型)
- [7.3 接入 DeepSeek API 完整教程](#7.3 接入 DeepSeek API 完整教程)
- [7.4 接入通义千问(阿里云百炼)](#7.4 接入通义千问(阿里云百炼))
- [7.5 接入智谱 GLM-4 Plus](#7.5 接入智谱 GLM-4 Plus)
- [7.6 接入本地 Ollama 模型](#7.6 接入本地 Ollama 模型)
- [7.7 配置文件详解](#7.7 配置文件详解)
- [7.8 代理与网络配置](#7.8 代理与网络配置)
- [八、DevEco Code 核心功能详解](#八、DevEco Code 核心功能详解)
-
- [8.1 智能代码生成](#8.1 智能代码生成)
- [8.2 页面 UI 生成](#8.2 页面 UI 生成)
- [8.3 万能卡片生成](#8.3 万能卡片生成)
- [8.4 代码重构与优化](#8.4 代码重构与优化)
- [8.5 Bug 诊断与修复](#8.5 Bug 诊断与修复)
- [8.6 工程辅助与构建管理](#8.6 工程辅助与构建管理)
- [8.7 知识问答与文档查询](#8.7 知识问答与文档查询)
- 九、斜杠命令与快捷键大全
-
- [9.1 高频必备命令](#9.1 高频必备命令)
- [9.2 会话与上下文管理命令](#9.2 会话与上下文管理命令)
- [9.3 模型与配置命令](#9.3 模型与配置命令)
- [9.4 项目级命令](#9.4 项目级命令)
- [9.5 调试与诊断命令](#9.5 调试与诊断命令)
- [9.6 快捷键一览](#9.6 快捷键一览)
- [9.7 MacOS 专属快捷键](#9.7 MacOS 专属快捷键)
- [十、实战案例:使用 DevEco Code 开发鸿蒙应用](#十、实战案例:使用 DevEco Code 开发鸿蒙应用)
-
- [10.1 实战一:从零创建 HarmonyOS 项目](#10.1 实战一:从零创建 HarmonyOS 项目)
- [10.2 实战二:AI 生成电商首页 UI(完整代码)](#10.2 实战二:AI 生成电商首页 UI(完整代码))
- [10.3 实战三:网络请求与数据绑定(完整代码)](#10.3 实战三:网络请求与数据绑定(完整代码))
- [10.4 实战四:万能卡片开发(完整代码)](#10.4 实战四:万能卡片开发(完整代码))
- [10.5 实战五:Bug 排查与修复](#10.5 实战五:Bug 排查与修复)
- [10.6 实战六:代码重构与性能优化](#10.6 实战六:代码重构与性能优化)
- [十一、与 DevEco Studio 协同工作](#十一、与 DevEco Studio 协同工作)
-
- [11.1 DevEco Studio MacOS 版安装](#11.1 DevEco Studio MacOS 版安装)
- [11.2 双工具协同工作流](#11.2 双工具协同工作流)
- [11.3 项目路径切换](#11.3 项目路径切换)
- [11.4 编译、签名与真机调试配合](#11.4 编译、签名与真机调试配合)
- [11.5 hdc 工具链配置](#11.5 hdc 工具链配置)
- 十二、高级配置与自定义
-
- [12.1 配置文件目录结构(MacOS 路径)](#12.1 配置文件目录结构(MacOS 路径))
- [12.2 自定义 Agent 行为与记忆文件](#12.2 自定义 Agent 行为与记忆文件)
- [12.3 MCP(Model Context Protocol)扩展](#12.3 MCP(Model Context Protocol)扩展)
- [12.4 自定义提示词模板](#12.4 自定义提示词模板)
- [12.5 环境变量与 Shell 集成](#12.5 环境变量与 Shell 集成)
- [12.6 iTerm2 深度集成](#12.6 iTerm2 深度集成)
- 十三、更新与升级
-
- [13.1 deveco upgrade 命令](#13.1 deveco upgrade 命令)
- [13.2 npm 重新安装升级](#13.2 npm 重新安装升级)
- [13.3 版本回退](#13.3 版本回退)
- [13.4 升级注意事项](#13.4 升级注意事项)
- 十四、完整卸载流程
-
- [14.1 卸载运行时数据](#14.1 卸载运行时数据)
- [14.2 npm 全局卸载](#14.2 npm 全局卸载)
- [14.3 清理残留配置与缓存](#14.3 清理残留配置与缓存)
- [14.4 卸载 Node.js(可选)](#14.4 卸载 Node.js(可选))
- [14.5 卸载 Homebrew(可选)](#14.5 卸载 Homebrew(可选))
- [14.6 卸载验证](#14.6 卸载验证)
- 十五、常见问题与解决方案(FAQ)
-
- [15.1 安装类问题](#15.1 安装类问题)
- [15.2 登录类问题](#15.2 登录类问题)
- [15.3 模型调用类问题](#15.3 模型调用类问题)
- [15.4 MacOS 特有问题](#15.4 MacOS 特有问题)
- [15.5 性能与稳定性问题](#15.5 性能与稳定性问题)
- 十六、总结
- 附录
-
- [附录 A:DevEco Code 完整命令参考表](#附录 A:DevEco Code 完整命令参考表)
- [附录 B:MacOS 环境变量与配置文件速查表](#附录 B:MacOS 环境变量与配置文件速查表)
- [附录 C:MacOS 终端命令速查](#附录 C:MacOS 终端命令速查)
- [附录D:模型 API 参数对照表](#附录D:模型 API 参数对照表)
- 学习资料与推荐资源
摘要
随着 HarmonyOS NEXT 生态在 2026 年的全面铺开,华为在 HDC 2026 期间正式发布了面向鸿蒙开发场景的 AI Agent 工具------DevEco Code。这款工具基于开源项目 OpenCode 深度定制,专为 HarmonyOS 应用及元服务开发进行了专项优化。它不仅深度理解 ArkTS 语法、声明式 UI 范式、Stage 模型、Hvigor 构建系统,更以终端原生(Terminal-Native)的交互形态,让开发者通过自然语言对话完成从代码生成、页面构建、Bug 修复到工程重构的全链路开发任务。
对于使用 MacOS 的鸿蒙开发者而言,DevEco Code 提供了与 Windows/Linux 完全一致的功能体验,但由于 MacOS 在包管理器、终端环境、权限模型、Shell 配置等方面的差异,安装和配置过程中存在一些独特的"坑"需要规避。本文以 MacOS(涵盖 Intel 与 Apple Silicon 双架构)为平台,从零基础出发,全面覆盖 Homebrew 环境搭建、Node.js 安装与版本管理、DevEco Code 安装与启动、华为账号登录、内置 GLM-5.1 免费模型使用、DeepSeek 等第三方模型接入、斜杠命令体系、实战开发案例(含完整代码与详细注释)、与 DevEco Studio 的协同工作流、高级自定义配置、MCP 扩展、版本更新升级以及完整卸载流程。
全文超过三万字,结构清晰、步骤详实、代码注释完善,力求为 MacOS 平台上的鸿蒙开发者提供一份"案头必备"的一站式操作手册。无论你是刚从 Windows 转到 MacOS 的开发者,还是 Mac 老用户初次接触鸿蒙生态,都能从本文中找到所需的答案。
目录
- 一、DevEco Code 概述与 MacOS 适配
- 1.1 什么是 DevEco Code
- 1.2 MacOS 平台的独特优势
- 1.3 Intel Mac 与 Apple Silicon Mac 的差异
- 1.4 DevEco Code 与 DevEco Studio、CodeGenie 的区别
- 1.5 核心能力总览
- 1.6 适用场景与目标用户
- 二、环境准备与前置条件
- 2.1 MacOS 版本要求
- 2.2 硬件配置建议
- 2.3 必备软件清单
- 2.4 华为开发者账号准备
- 2.5 Xcode Command Line Tools 安装
- 三、安装 Homebrew 包管理器
- 3.1 Homebrew 简介
- 3.2 安装 Homebrew
- 3.3 Apple Silicon 上的路径差异
- 3.4 配置 Homebrew 国内镜像
- 3.5 Homebrew 常用命令速查
- 四、安装 Node.js 与 npm 环境
- 4.1 方案一:通过 Homebrew 安装 Node.js
- 4.2 方案二:通过 nvm 管理多版本 Node.js
- 4.3 方案三:通过 fnm 管理 Node.js(推荐)
- 4.4 验证 Node.js 与 npm 安装
- 4.5 配置 npm 国内镜像源
- 4.6 解决 MacOS 全局安装权限问题
- 4.7 Shell 配置文件详解(zsh vs bash)
- 五、安装 DevEco Code
- 5.1 npm 全局安装
- 5.2 安装过程全记录
- 5.3 验证安装成功
- 5.4 Apple Silicon 特殊注意事项
- 5.5 安装失败常见原因与排查
- 六、首次启动与登录配置
- 6.1 终端选择与启动方式
- 6.2 数据库迁移与初始化
- 6.3 华为开发者账号登录
- 6.4 隐私政策与使用条款
- 6.5 登录状态管理与凭证安全
- 七、模型配置与第三方模型接入
- 7.1 内置免费模型 GLM-5.1
- 7.2 使用 /model 命令切换模型
- 7.3 接入 DeepSeek API 完整教程
- 7.4 接入通义千问(阿里云百炼)
- 7.5 接入智谱 GLM-4 Plus
- 7.6 接入本地 Ollama 模型
- 7.7 配置文件详解
- 7.8 代理与网络配置
- 八、DevEco Code 核心功能详解
- 8.1 智能代码生成
- 8.2 页面 UI 生成
- 8.3 万能卡片生成
- 8.4 代码重构与优化
- 8.5 Bug 诊断与修复
- 8.6 工程辅助与构建管理
- 8.7 知识问答与文档查询
- 九、斜杠命令与快捷键大全
- 9.1 高频必备命令
- 9.2 会话与上下文管理命令
- 9.3 模型与配置命令
- 9.4 项目级命令
- 9.5 调试与诊断命令
- 9.6 快捷键一览
- 9.7 MacOS 专属快捷键
- 十、实战案例:使用 DevEco Code 开发鸿蒙应用
- 10.1 实战一:从零创建 HarmonyOS 项目
- 10.2 实战二:AI 生成电商首页 UI(完整代码)
- 10.3 实战三:网络请求与数据绑定(完整代码)
- 10.4 实战四:万能卡片开发(完整代码)
- 10.5 实战五:Bug 排查与修复
- 10.6 实战六:代码重构与性能优化
- 十一、与 DevEco Studio 协同工作
- 11.1 DevEco Studio MacOS 版安装
- 11.2 双工具协同工作流
- 11.3 项目路径切换
- 11.4 编译、签名与真机调试配合
- 11.5 hdc 工具链配置
- 十二、高级配置与自定义
- 12.1 配置文件目录结构(MacOS 路径)
- 12.2 自定义 Agent 行为与记忆文件
- 12.3 MCP(Model Context Protocol)扩展
- 12.4 自定义提示词模板
- 12.5 环境变量与 Shell 集成
- 12.6 iTerm2 深度集成
- 十三、更新与升级
- 13.1 deveco upgrade 命令
- 13.2 npm 重新安装升级
- 13.3 版本回退
- 13.4 升级注意事项
- 十四、完整卸载流程
- 14.1 卸载运行时数据
- 14.2 npm 全局卸载
- 14.3 清理残留配置与缓存
- 14.4 卸载 Node.js(可选)
- 14.5 卸载 Homebrew(可选)
- 14.6 卸载验证
- 十五、常见问题与解决方案(FAQ)
- 15.1 安装类问题
- 15.2 登录类问题
- 15.3 模型调用类问题
- 15.4 MacOS 特有问题
- 15.5 性能与稳定性问题
- 十六、总结
- 附录
- 附录 A:DevEco Code 完整命令参考表
- 附录 B:MacOS 环境变量与配置文件速查表
- 附录 C:MacOS 终端命令速查
- 附录 D:模型 API 参数对照表
- 附录 E:Homebrew 常用 Formulae 列表
- 学习资料与推荐资源
一、DevEco Code 概述与 MacOS 适配
1.1 什么是 DevEco Code
DevEco Code 是华为在 2026 年华为开发者大会(HDC 2026)期间正式发布的一款面向 HarmonyOS 开发场景的 终端 AI Agent 工具 。它基于开源项目 OpenCode 深度扩展开发,并针对 HarmonyOS 开发进行了全方位的专项优化。
与传统 IDE 插件式 AI 助手不同,DevEco Code 采用了**终端 TUI(Terminal User Interface)**的交互形态。开发者在 MacOS 的 Terminal.app、iTerm2 或 Warp 等终端模拟器中输入一行命令即可启动工具,随后通过自然语言对话的方式,让 AI Agent 直接读取项目代码、理解工程结构、生成 ArkTS 代码、执行构建命令,甚至自动修复编译错误。
从技术架构来看,DevEco Code 具备以下关键特征:
- 终端原生:基于 Terminal 的富文本交互界面,支持代码高亮、文件差异预览、命令执行确认
- Agent 架构:具备自主推理与工具调用能力,可根据开发者指令自动完成多步骤开发任务
- HarmonyOS 专项优化:深度理解 ArkTS 语法体系、声明式 UI 范式、Stage 模型、Hvigor 构建系统、ohpm 包管理
- 多模型支持:内置免费 GLM-5.1 模型通道,同时支持接入 DeepSeek、通义千问等第三方大模型
- 跨平台兼容:在 MacOS、Windows、Linux 上提供一致的功能体验
1.2 MacOS 平台的独特优势
对于鸿蒙开发者而言,MacOS 平台具有以下独特优势:
- Unix 基因:MacOS 底层基于 BSD Unix,终端环境与服务器/Linux 高度一致,命令行工具兼容性极佳
- Homebrew 生态:强大的包管理器让环境搭建变得简单优雅
- Apple Silicon 性能:M1/M2/M3/M4 芯片的统一内存架构在运行 DevEco Studio 模拟器时表现优异
- 开发体验:MacOS 的字体渲染、Retina 显示屏、触控板手势等提供了出色的开发体验
- 终端生态丰富:iTerm2、Warp、Alacritty 等终端模拟器提供了远超 Windows 的终端使用体验
1.3 Intel Mac 与 Apple Silicon Mac 的差异
| 对比项 | Intel Mac | Apple Silicon Mac (M1/M2/M3/M4) |
|---|---|---|
| 架构 | x86_64 | arm64 |
| Homebrew 路径 | /usr/local/ |
/opt/homebrew/ |
| Node.js 兼容性 | 完全兼容 | 原生 arm64 支持(v16+) |
| Rosetta 2 | 不需要 | 运行 x86 软件时需要 |
| DevEco Code 运行 | 原生运行 | 原生运行 |
| DevEco Studio | 支持 | 支持(推荐 Apple Silicon 版) |
重要提示 :本文中的所有路径示例默认使用 Apple Silicon 路径(
/opt/homebrew/)。如果你使用 Intel Mac,请将对应路径替换为/usr/local/。
1.4 DevEco Code 与 DevEco Studio、CodeGenie 的区别
| 对比维度 | DevEco Studio | CodeGenie | DevEco Code |
|---|---|---|---|
| 定位 | 官方集成开发环境 | IDE 内置 AI 插件 | 终端 AI Agent 工具 |
| 技术基座 | IntelliJ IDEA | DevEco Studio 插件 | OpenCode 开源项目 |
| 交互方式 | GUI 图形界面 | IDE 侧边栏 | 终端 TUI |
| 核心能力 | 编辑/预览/调试/打包 | 代码补全/问答 | Agent 自主编程 |
| AI 深度 | 无内置 AI | Copilot 模式 | Agent 模式 |
| 独立运行 | 是 | 否 | 是 |
| MacOS 支持 | Intel + Apple Silicon | Intel + Apple Silicon | Intel + Apple Silicon |
1.5 核心能力总览
DevEco Code 的核心能力涵盖鸿蒙开发的方方面面:
- 智能代码生成:根据自然语言描述生成完整 ArkTS 代码
- 页面 UI 生成:从描述直接生成声明式 UI 页面
- 万能卡片生成:HarmonyOS Widget 专项支持
- 代码重构优化:自动分析并重构代码
- Bug 诊断修复:智能定位并修复编译/运行时错误
- 工程辅助:依赖管理、构建配置、权限声明
- 知识问答:基于 HarmonyOS 官方文档的精准回答
1.6 适用场景与目标用户
适用场景:
- 快速原型开发:自然语言 → 可运行代码
- 复杂业务逻辑实现:网络请求、数据持久化、状态管理
- 遗留代码重构:导入旧项目,AI 辅助现代化改造
- 学习探索:新手通过与 AI 对话学习 ArkTS
- 效率提升:资深开发者将重复性工作交给 AI
目标用户:
- HarmonyOS 应用开发者(MacOS 平台)
- 鸿蒙元服务开发者
- 对 AI 辅助编程感兴趣的移动端开发者
- 从 iOS 开发转向鸿蒙开发的开发者
- 鸿蒙技术教育工作者
二、环境准备与前置条件
2.1 MacOS 版本要求
| MacOS 版本 | 支持状态 | 备注 |
|---|---|---|
| MacOS 15 (Sequoia) | ✅ 完全支持 | 推荐 |
| MacOS 14 (Sonoma) | ✅ 完全支持 | 推荐 |
| MacOS 13 (Ventura) | ✅ 完全支持 | |
| MacOS 12 (Monterey) | ✅ 支持 | 建议升级 |
| MacOS 11 (Big Sur) | ⚠️ 部分支持 | Node.js 新版可能不兼容 |
| MacOS 10.15 及以下 | ❌ 不支持 | 已过时 |
建议:使用 MacOS 14 Sonoma 或 MacOS 15 Sequoia,以获得最佳兼容性。
2.2 硬件配置建议
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| 内存 | 8 GB | 16 GB 及以上 |
| 硬盘 | 10 GB 可用空间 | 100 GB SSD |
| 处理器 | Intel i5 / M1 | M2/M3/M4 Pro 或 Max |
| 显示器 | 1280×800 | Retina 显示屏 |
| 网络 | 宽带连接 | 稳定的宽带(AI 对话需要) |
说明:DevEco Code 的 AI 推理在云端完成,本地主要消耗在于终端渲染和 Node.js 运行时。但如果同时运行 DevEco Studio 进行编译预览,Apple Silicon + 16GB 内存是最佳选择。
2.3 必备软件清单
| 软件 | 版本要求 | 用途 | 必须 |
|---|---|---|---|
| Xcode CLT | 最新版 | 编译工具链 | ✅ |
| Homebrew | 最新版 | 包管理器 | ✅ |
| Node.js | v18+ (推荐 v20 LTS) | 运行时 | ✅ |
| npm | v9+(随 Node.js) | 包管理 | ✅ |
| Git | v2.30+ | 版本控制 | ⚠️ 强烈建议 |
| DevEco Studio | 6.1+ | 鸿蒙 IDE | ⚠️ 强烈建议 |
| iTerm2 | 最新版 | 终端增强 | 💡 推荐 |
2.4 华为开发者账号准备
- 注册华为开发者账号 :访问 华为开发者联盟,点击注册
- 完成实名认证:个人或企业开发者均需实名认证
- 了解免费额度:内置 GLM-5.1 模型免费提供,单账号默认每分钟 50 次请求
2.5 Xcode Command Line Tools 安装
Xcode Command Line Tools(CLT)是 MacOS 上的基础编译工具链,包含 gcc、clang、make、git 等工具,是安装 Homebrew 和编译原生 npm 模块的前提条件。
检查是否已安装:
bash
# 检查 git 是否可用
git --version
# 检查 clang 是否可用
clang --version
安装 Command Line Tools:
bash
# 触发安装提示
xcode-select --install
执行后会弹出系统对话框,点击"安装"按钮,等待下载安装完成(约 1-3 GB,取决于网络速度)。
验证安装:
bash
# 查看 CLT 安装路径
xcode-select -p
# 输出:/Applications/Xcode.app/Contents/Developer 或 /Library/Developer/CommandLineTools
# 查看 git 版本
git --version
# 输出:git version 2.x.x
注意 :某些情况下,MacOS 升级后 CLT 可能需要重新安装。如果遇到编译错误,可以执行
sudo rm -rf /Library/Developer/CommandLineTools && xcode-select --install重新安装。
三、安装 Homebrew 包管理器
3.1 Homebrew 简介
Homebrew 是 MacOS(和 Linux)上最流行的包管理器,被誉为"MacOS 缺失的包管理器"。它可以方便地安装、更新、卸载各种开发工具和库,是 MacOS 开发者的必备神器。
DevEco Code 本身不需要通过 Homebrew 安装(它通过 npm 安装),但 Node.js、Git 以及许多其他开发工具都推荐使用 Homebrew 来管理。
3.2 安装 Homebrew
官方安装方式:
bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
安装过程中会提示你输入管理员密码,并显示即将执行的操作。按 Enter 确认即可。
国内镜像安装方式(推荐,速度更快):
bash
# 使用清华大学镜像
/bin/bash -c "$(curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/install/install.sh)"
或使用中科大镜像:
bash
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.ustc.edu.cn/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.ustc.edu.cn/homebrew-core.git"
export HOMEBREW_API_DOMAIN="https://mirrors.ustc.edu.cn/homebrew-bottles/api"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.ustc.edu.cn/homebrew-bottles"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
3.3 Apple Silicon 上的路径差异
Apple Silicon(M1/M2/M3/M4)Mac 上,Homebrew 安装在 /opt/homebrew/ 目录下(而非 Intel Mac 的 /usr/local/)。安装完成后,需要将 Homebrew 添加到 PATH 中。
Apple Silicon 配置:
bash
# 将 Homebrew 添加到当前 Shell 的 PATH
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
Intel Mac 配置:
bash
# Intel Mac 通常自动配置好,如果需要手动添加
echo 'eval "$(/usr/local/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/usr/local/bin/brew shellenv)"
验证安装:
bash
# 查看 Homebrew 版本
brew --version
# 输出:Homebrew 4.x.x
# 检查 Homebrew 健康状态
brew doctor
3.4 配置 Homebrew 国内镜像
为了加速 Homebrew 的下载速度,建议配置国内镜像源:
bash
# 使用清华大学镜像
export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles"
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git"
export HOMEBREW_PIP_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"
将上述环境变量写入 Shell 配置文件以永久生效:
bash
# 对于 zsh(MacOS 默认 Shell)
cat >> ~/.zshrc << 'EOF'
# Homebrew 清华大学镜像
export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles"
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git"
EOF
# 使配置立即生效
source ~/.zshrc
3.5 Homebrew 常用命令速查
bash
# 安装软件
brew install <package>
# 卸载软件
brew uninstall <package>
# 更新 Homebrew 自身
brew update
# 升级已安装的软件
brew upgrade <package>
# 搜索软件
brew search <keyword>
# 查看软件信息
brew info <package>
# 列出已安装的软件
brew list
# 清理缓存
brew cleanup
# 检查健康状态
brew doctor
四、安装 Node.js 与 npm 环境
DevEco Code 基于 Node.js 运行,正确安装和管理 Node.js 版本是至关重要的一步。本章提供三种安装方案,你可以根据自身需求选择。
4.1 方案一:通过 Homebrew 安装 Node.js
这是最简单的安装方式,适合不需要频繁切换 Node.js 版本的用户。
bash
# 安装最新 LTS 版本的 Node.js
brew install node@20
# 安装完成后,可能需要链接到 PATH
brew link node@20 --force --overwrite
# 验证安装
node -v # 输出:v20.x.x
npm -v # 输出:10.x.x
如果需要安装最新 Current 版本:
bash
brew install node
Homebrew 安装方式的优缺点:
| 优点 | 缺点 |
|---|---|
| 一条命令搞定 | 不方便切换多版本 |
| 自动管理依赖 | 升级可能影响全局 |
| 与 MacOS 集成好 | 需要 brew link 操作 |
4.2 方案二:通过 nvm 管理多版本 Node.js
nvm(Node Version Manager) 是最流行的 Node.js 版本管理工具,适合需要在多个项目间切换 Node.js 版本的开发者。
步骤 1:安装 nvm
bash
# 使用官方安装脚本
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
安装脚本会自动将 nvm 配置添加到你的 ~/.zshrc 文件中。
步骤 2:使配置生效
bash
source ~/.zshrc
步骤 3:验证 nvm 安装
bash
nvm --version
# 输出:0.40.1
步骤 4:使用 nvm 安装 Node.js
bash
# 查看可用的 Node.js 版本
nvm ls-remote
# 安装 LTS 版本(推荐)
nvm install --lts
# 或指定版本
nvm install 20.18.1
# 查看已安装的版本
nvm ls
# 切换到指定版本
nvm use 20.18.1
# 设置默认版本
nvm alias default 20.18.1
nvm 常用命令:
bash
nvm install <version> # 安装指定版本
nvm use <version> # 切换版本
nvm alias default <ver> # 设置默认版本
nvm ls # 列出已安装版本
nvm ls-remote # 列出远程可用版本
nvm uninstall <version> # 卸载指定版本
nvm current # 查看当前版本
4.3 方案三:通过 fnm 管理 Node.js(推荐)
fnm(Fast Node Manager) 是用 Rust 编写的 Node.js 版本管理器,比 nvm 更快,且对 Apple Silicon 支持更好。这是本文最推荐的方案。
步骤 1:通过 Homebrew 安装 fnm
bash
brew install fnm
步骤 2:配置 Shell 集成
bash
# 对于 zsh(MacOS 默认)
echo 'eval "$(fnm env --use-on-cd --shell zsh)"' >> ~/.zshrc
source ~/.zshrc
如果你使用 bash:
bash
echo 'eval "$(fnm env --use-on-cd --shell bash)"' >> ~/.bash_profile
source ~/.bash_profile
步骤 3:使用 fnm 安装 Node.js
bash
# 查看可用版本
fnm ls-remote | grep "v20"
# 安装 LTS 版本
fnm install --lts
# 或安装指定版本
fnm install 20.18.1
# 设置为默认版本
fnm default 20.18.1
# 使用指定版本
fnm use 20.18.1
# 查看已安装版本
fnm ls
fnm 的 --use-on-cd 功能:
配置了 --use-on-cd 后,当你 cd 进入一个包含 .node-version 或 .nvmrc 文件的项目目录时,fnm 会自动切换到对应的 Node.js 版本。这对于维护多个项目的开发者来说非常实用。
bash
# 在项目中创建 .node-version 文件
echo "20.18.1" > .node-version
# cd 进入项目目录时自动切换
cd ~/HarmonyOSProjects/MyApp
# 输出:Using Node.js version 20.18.1
4.4 验证 Node.js 与 npm 安装
无论使用哪种安装方式,安装完成后都需要验证:
bash
# 验证 Node.js
node -v
# 期望输出:v20.x.x
# 验证 npm
npm -v
# 期望输出:10.x.x
# 验证 npx
npx -v
# 期望输出:10.x.x
# 查看 Node.js 安装路径
which node
# Apple Silicon + Homebrew: /opt/homebrew/bin/node
# fnm: /Users/xxx/Library/Application Support/fnm/aliases/default/bin/node
# 查看 npm 全局安装路径
npm config get prefix
验证 Node.js 架构(Apple Silicon 重要):
bash
# 查看 Node.js 的 CPU 架构
node -e "console.log(process.arch)"
# Apple Silicon 原生: arm64
# Rosetta 2 翻译: x64
建议:在 Apple Silicon Mac 上,确保 Node.js 是 arm64 原生版本,而非通过 Rosetta 2 翻译的 x64 版本,以获得最佳性能。
4.5 配置 npm 国内镜像源
bash
# 设置 npmmirror(原淘宝镜像)
npm config set registry https://registry.npmmirror.com
# 验证
npm config get registry
# 输出:https://registry.npmmirror.com/
# 如需恢复官方源
npm config set registry https://registry.npmjs.org/
使用 nrm 管理多个镜像源:
bash
# 安装 nrm
npm install -g nrm
# 查看所有镜像源
nrm ls
# 切换到 npmmirror
nrm use npmmirror
# 测试速度
nrm test
4.6 解决 MacOS 全局安装权限问题
在 MacOS 上,使用 Homebrew 安装的 Node.js 进行全局安装时,有时会遇到权限问题:
bash
npm install -g @deveco/deveco-code
# 报错:EACCES: permission denied
解决方案一:修改 npm 全局目录权限
bash
# 查看 npm 全局目录
npm config get prefix
# 修改目录所有者(替换为你的用户名)
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
解决方案二:更改 npm 全局目录到用户目录
bash
# 创建自定义全局目录
mkdir -p ~/.npm-global
# 配置 npm 使用新目录
npm config set prefix '~/.npm-global'
# 将新目录添加到 PATH
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
# 现在可以无需 sudo 全局安装
npm install -g @deveco/deveco-code
解决方案三:使用 fnm/nvm 避免权限问题
如果你使用 fnm 或 nvm 管理 Node.js,全局安装默认在用户目录下,不需要 sudo,也不会有权限问题。这是推荐使用版本管理器的原因之一。
4.7 Shell 配置文件详解(zsh vs bash)
MacOS 从 Catalina(10.15)开始默认使用 zsh 作为 Shell。了解 Shell 配置文件的位置和加载顺序对于环境配置至关重要。
zsh 配置文件加载顺序:
1. /etc/zshenv # 系统级,总是被加载
2. ~/.zshenv # 用户级,总是被加载
3. /etc/zprofile # 系统级,登录 Shell 时加载
4. ~/.zprofile # 用户级,登录 Shell 时加载
5. /etc/zshrc # 系统级,交互式 Shell 时加载
6. ~/.zshrc # 用户级,交互式 Shell 时加载(最常用!)
7. /etc/zlogin # 系统级,登录 Shell 时加载
8. ~/.zlogin # 用户级,登录 Shell 时加载
日常开发中,绝大部分配置应写入 ~/.zshrc。
查看当前使用的 Shell:
bash
echo $SHELL
# 输出:/bin/zsh
切换到 bash(如果需要):
bash
chsh -s /bin/bash
一个典型的 ~/.zshrc 配置示例:
bash
# =============================================
# ~/.zshrc - MacOS 开发者 Shell 配置
# =============================================
# --- Homebrew ---
# Apple Silicon
eval "$(/opt/homebrew/bin/brew shellenv)"
# Homebrew 国内镜像
export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles"
# --- fnm (Node.js 版本管理) ---
eval "$(fnm env --use-on-cd --shell zsh)"
# --- npm 全局目录(如果手动配置了) ---
# export PATH=~/.npm-global/bin:$PATH
# --- 环境变量 ---
export LANG=en_US.UTF-8
export EDITOR=vim
# --- 别名 ---
alias ll='ls -la'
alias gs='git status'
alias gp='git push'
# --- DevEco Code 环境变量 ---
# export DEVECO_MODEL=glm-5
# export DEVECO_LOG_LEVEL=info
五、安装 DevEco Code
环境准备就绪后,终于可以安装 DevEco Code 了。
5.1 npm 全局安装
打开终端,执行以下命令:
bash
npm install -g @deveco/deveco-code
参数详解:
| 参数 | 全称 | 含义 |
|---|---|---|
npm install |
- | npm 安装命令 |
-g |
--global |
全局安装,使 deveco 命令全局可用 |
@deveco/deveco-code |
- | npm 包名(华为官方命名空间) |
备选安装命令(OpenHarmony SIG 版本):
bash
npm install -g @openharmony-sig/deveco-code
5.2 安装过程全记录
bash
$ npm install -g @deveco/deveco-code
added 287 packages in 38s
47 packages are looking for funding
run `npm fund` for details
$
安装过程中,npm 会自动完成以下工作:
- 解析
@deveco/deveco-code的完整依赖树 - 从 npm 仓库下载所有依赖包(约 50-100 MB)
- 将包文件解压到全局
node_modules目录 - 在 npm 全局
bin目录创建deveco可执行文件的符号链接 - 注册
deveco命令到系统 PATH
全局安装位置(因安装方式不同而异):
bash
# 查看安装位置
npm list -g @deveco/deveco-code
# 查看全局 bin 目录
npm config get prefix
# fnm: /Users/xxx/Library/Application Support/fnm/aliases/default/
# Homebrew: /opt/homebrew/
# 自定义: ~/.npm-global/
5.3 验证安装成功
bash
# 查看版本号
deveco --version
# 输出:1.0.0(或更高版本)
# 查看帮助信息
deveco --help
# 查看 deveco 命令位置
which deveco
如果以上命令都能正常执行并输出,恭喜,DevEco Code 安装成功!
5.4 Apple Silicon 特殊注意事项
在 Apple Silicon Mac 上安装 DevEco Code 时,需要注意以下几点:
-
确保终端以 arm64 模式运行:如果你使用 Rosetta 2 运行终端(x64 模式),安装的 Node.js 和 npm 包可能是 x64 版本。
bash# 检查终端架构 arch # 应该输出:arm64 # 如果输出 i386 或 x86_64,说明在 Rosetta 模式下 # 解决方法:确保终端应用没有勾选"使用 Rosetta 打开" -
原生 npm 模块编译:部分 npm 依赖包含原生 C++ 扩展,需要确保 Xcode CLT 已安装且架构匹配。
-
Homebrew 路径 :Apple Silicon 的 Homebrew 在
/opt/homebrew/,确保 PATH 配置正确。
5.5 安装失败常见原因与排查
问题 1:EACCES 权限错误
bash
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /opt/homebrew/lib/node_modules/@deveco
解决:参考 4.6 节的权限解决方案,或使用 fnm/nvm 避免此问题。
问题 2:404 Not Found
bash
npm ERR! code E404
npm ERR! 404 Not Found - @deveco/deveco-code
解决:切换到官方源:
bash
npm config set registry https://registry.npmjs.org/
npm install -g @deveco/deveco-code
问题 3:node-gyp 编译失败
bash
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
解决:确保 Xcode CLT 已正确安装:
bash
xcode-select --install
# 或重新安装
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install
问题 4:网络超时
bash
npm ERR! code ETIMEDOUT
npm ERR! network request failed
解决:使用国内镜像或配置代理:
bash
# 切换镜像源
npm config set registry https://registry.npmmirror.com
# 或配置代理
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
六、首次启动与登录配置
6.1 终端选择与启动方式
DevEco Code 可以在 MacOS 上的任何终端模拟器中运行。以下是几种推荐的终端选择:
Terminal.app(系统自带):
- 位于
/Applications/Utilities/Terminal.app - 功能够用,但体验一般
- 可通过 Spotlight(
Cmd+Space)搜索 "Terminal" 打开
iTerm2(推荐):
- 功能最强大的 MacOS 终端模拟器
- 安装:
brew install --cask iterm2 - 支持分屏、热键窗口、丰富的配色方案
Warp:
- 新一代 AI 终端
- 安装:
brew install --cask warp
启动 DevEco Code:
bash
# 方式 1:在任意目录下启动
deveco
# 方式 2:先进入项目目录再启动(推荐)
cd ~/HarmonyOSProjects/MyApp
deveco
# 方式 3:指定项目路径启动
deveco --cwd ~/HarmonyOSProjects/MyApp
6.2 数据库迁移与初始化
首次启动时,DevEco Code 会自动执行以下初始化操作:
╭─────────────────────────────────────────╮
│ DevEco Code v1.0.0 │
│ HarmonyOS AI Agent for Developers │
╰─────────────────────────────────────────╯
Initializing DevEco Code...
◐ Running database migrations...
✓ Creating schema...
✓ Initializing tables...
✓ Migration completed successfully.
◐ Checking authentication...
⚠ Not authenticated. Please log in.
初始化过程中,DevEco Code 会在 ~/.deveco/ 目录下创建本地数据库和配置文件:
~/.deveco/
├── data.db # 本地 SQLite 数据库
├── ai/
│ ├── config.json # 模型配置
│ ├── prompts/ # 提示词模板
│ └── history/ # 对话历史
├── auth/
│ └── credentials.json # 登录凭证
├── cache/ # 缓存数据
└── logs/
└── deveco-code.log # 运行日志
6.3 华为开发者账号登录
DevEco Code 提供交互式登录流程:
- 在 TUI 界面中,使用方向键选择 【Login】 或 【Sign in with HUAWEI account】
- 按
Enter确认 - DevEco Code 自动打开系统默认浏览器,跳转到华为认证页面
- 在浏览器中输入华为开发者账号和密码
- 完成登录后,浏览器显示"授权成功"
- 返回终端,DevEco Code 自动检测登录状态
如果浏览器没有自动打开:
bash
# 手动打开登录链接(终端中会显示)
open "https://developer.huawei.com/consumer/cn/auth?..."
验证登录状态:
bash
deveco status
# 输出应包含:Authenticated: true
6.4 隐私政策与使用条款
首次登录后,DevEco Code 会展示隐私安全政策和使用条款。使用方向键滚动阅读,选择 【Agree】 确认。
6.5 登录状态管理与凭证安全
bash
# 查看登录状态
deveco status
# 退出登录
deveco logout
# 重新登录
deveco
# 在 TUI 中选择 Login
凭证安全建议:
- 登录凭证保存在
~/.deveco/auth/credentials.json中(加密存储) - 切勿将
~/.deveco/目录提交到 Git 仓库 - 在共享电脑上使用完毕后执行
deveco logout - 建议在
.gitignore中添加.deveco/规则
七、模型配置与第三方模型接入
7.1 内置免费模型 GLM-5.1
DevEco Code 开箱即用地内置了 GLM-5.1 模型:
| 属性 | 说明 |
|---|---|
| 模型 | GLM-5.1 |
| 提供方 | 华为 DevEco Code 服务 |
| 费用 | 免费 |
| 速率限制 | 每分钟 50 次请求 |
| 上下文窗口 | 128K tokens |
| 工具调用 | 支持 |
7.2 使用 /model 命令切换模型
在交互式会话中:
/model
弹出模型选择列表,使用方向键选择,Enter 确认。
7.3 接入 DeepSeek API 完整教程
步骤 1:获取 API Key
访问 DeepSeek 开放平台,注册登录后,在 "API Keys" 页面创建密钥。
步骤 2:通过 /model 命令配置
在 DevEco Code 中:
/model
选择 "Add Provider",按提示输入:
- Provider Name:
deepseek - API Base URL:
https://api.deepseek.com - API Key:
sk-你的密钥 - Model ID:
deepseek-chat或deepseek-coder
步骤 3:直接编辑配置文件
bash
# 打开配置文件
vim ~/.deveco/ai/config.json
写入以下内容(详细注释版):
json
{
"provider": {
"deveco": {
"name": "DevEco Code",
"models": {
"glm-5": {
"tool_call": true,
"limit": 50
}
}
},
"deepseek": {
"name": "DeepSeek",
"api_base": "https://api.deepseek.com",
"api_key": "sk-your-deepseek-api-key-here",
"models": {
"deepseek-chat": {
"tool_call": true,
"context_window": 65536,
"max_tokens": 8192,
"temperature": 0.7
},
"deepseek-coder": {
"tool_call": true,
"context_window": 65536,
"max_tokens": 8192,
"temperature": 0.3
}
}
}
}
}
步骤 4:验证
你好,请告诉我你是什么模型
7.4 接入通义千问(阿里云百炼)
json
{
"qwen": {
"name": "通义千问",
"api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"api_key": "sk-your-qwen-api-key",
"models": {
"qwen-max": {
"tool_call": true,
"context_window": 32768
},
"qwen-plus": {
"tool_call": true,
"context_window": 131072
}
}
}
}
7.5 接入智谱 GLM-4 Plus
json
{
"zhipu": {
"name": "智谱 AI",
"api_base": "https://open.bigmodel.cn/api/paas/v4",
"api_key": "your-zhipu-api-key",
"models": {
"glm-4-plus": {
"tool_call": true,
"context_window": 128000
}
}
}
}
7.6 接入本地 Ollama 模型
Ollama 是在 MacOS 上运行本地大模型的最佳工具,完全离线运行,保护隐私。
安装 Ollama:
bash
brew install ollama
下载并运行模型:
bash
# 启动 Ollama 服务
ollama serve &
# 下载代码模型
ollama pull qwen2.5-coder:14b
# 下载通用模型
ollama pull llama3.1:8b
在 DevEco Code 中配置:
json
{
"ollama": {
"name": "Ollama Local",
"api_base": "http://localhost:11434/v1",
"api_key": "ollama",
"models": {
"qwen2.5-coder:14b": {
"tool_call": true,
"context_window": 32768
},
"llama3.1:8b": {
"tool_call": false,
"context_window": 8192
}
}
}
}
7.7 配置文件详解
~/.deveco/ai/config.json 的完整结构:
json
{
"provider": {
"<provider_id>": {
"name": "显示名称",
"api_base": "API 基础地址",
"api_key": "API 密钥",
"models": {
"<model_id>": {
"tool_call": true,
"context_window": 65536,
"max_tokens": 8192,
"temperature": 0.7,
"limit": 60
}
}
}
},
"mcp": {
"servers": []
},
"preferences": {
"default_model": "glm-5",
"auto_compact_threshold": 80,
"theme": "dark"
}
}
7.8 代理与网络配置
MacOS 上配置代理:
bash
# 在 ~/.zshrc 中添加代理函数
cat >> ~/.zshrc << 'EOF'
# --- 代理开关 ---
proxy_on() {
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890
echo "✓ 代理已开启"
}
proxy_off() {
unset http_proxy https_proxy all_proxy
echo "✗ 代理已关闭"
}
EOF
source ~/.zshrc
# 使用
proxy_on # 开启代理
proxy_off # 关闭代理
八、DevEco Code 核心功能详解
8.1 智能代码生成
DevEco Code 能够根据自然语言描述生成完整的 ArkTS 代码。以下是一个详细的代码生成示例。
开发者输入:
帮我创建一个用户管理的数据模型类,支持增删改查操作,
使用 @ohos.data.relationalStore 实现本地持久化。
DevEco Code 生成的代码(带详细注释):
typescript
// ===================================================
// 文件:src/main/ets/model/UserModel.ets
// 描述:用户数据模型,基于关系型数据库实现本地持久化
// ===================================================
// 导入关系型数据库模块
import relationalStore from '@ohos.data.relationalStore';
// 导入通用错误码
import { BusinessError } from '@ohos.base';
// 导入应用上下文
import common from '@ohos.app.ability.common';
/**
* 用户数据接口定义
* 定义用户表的结构和字段类型
*/
export interface UserInfo {
id?: number; // 用户 ID,主键自增
name: string; // 用户名称
email: string; // 电子邮箱
phone: string; // 手机号码
avatar?: string; // 头像 URL(可选)
createTime?: number; // 创建时间戳
updateTime?: number; // 更新时间戳
}
/**
* 数据库配置常量
* 集中管理数据库相关的配置信息
*/
const DB_CONFIG: relationalStore.StoreConfig = {
name: 'user_store.db', // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S1 // 安全等级 S1
};
/**
* SQL 建表语句
* 定义 user_info 表的结构
*/
const SQL_CREATE_TABLE = `
CREATE TABLE IF NOT EXISTS user_info (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL,
phone TEXT NOT NULL DEFAULT '',
avatar TEXT DEFAULT '',
create_time INTEGER DEFAULT (strftime('%s','now')),
update_time INTEGER DEFAULT (strftime('%s','now'))
)
`;
/**
* UserModel 类
* 封装用户数据的增删改查操作
*
* 使用示例:
* const model = await UserModel.getInstance(context);
* const users = await model.queryAll();
* const id = await model.insert({ name: '张三', email: 'zhang@example.com', phone: '13800138000' });
*/
export class UserModel {
// 关系型数据库实例(单例)
private rdbStore: relationalStore.RdbStore | null = null;
// 类级别的单例实例
private static instance: UserModel | null = null;
/**
* 私有构造函数,防止外部直接 new
* 使用 getInstance() 获取实例
*/
private constructor() {}
/**
* 获取 UserModel 单例实例
* @param context - 应用上下文,用于获取数据库路径
* @returns UserModel 实例
*/
static async getInstance(context: common.UIAbilityContext): Promise<UserModel> {
// 如果实例不存在,创建新实例并初始化数据库
if (!UserModel.instance) {
UserModel.instance = new UserModel();
await UserModel.instance.initDatabase(context);
}
return UserModel.instance;
}
/**
* 初始化数据库连接
* 创建数据库文件并执行建表语句
* @param context - 应用上下文
*/
private async initDatabase(context: common.UIAbilityContext): Promise<void> {
try {
// 获取 RDB 存储实例
this.rdbStore = await relationalStore.getRdbStore(context, DB_CONFIG);
// 执行建表 SQL
await this.rdbStore.executeSql(SQL_CREATE_TABLE);
console.info('[UserModel] 数据库初始化成功');
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 数据库初始化失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 新增用户记录
* @param user - 用户信息对象(不需要 id 和时间戳字段)
* @returns 新插入记录的 ID
*/
async insert(user: UserInfo): Promise<number> {
if (!this.rdbStore) {
throw new Error('[UserModel] 数据库未初始化');
}
// 构建值桶(ValueBucket),相当于 SQL 的 INSERT VALUES
const valueBucket: relationalStore.ValuesBucket = {
name: user.name,
email: user.email,
phone: user.phone,
avatar: user.avatar ?? '',
create_time: Date.now(),
update_time: Date.now()
};
try {
// 执行插入操作,返回新记录的 rowId
const rowId = await this.rdbStore.insert('user_info', valueBucket);
console.info(`[UserModel] 插入成功, rowId = ${rowId}`);
return rowId;
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 插入失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 根据 ID 删除用户
* @param id - 用户 ID
* @returns 被删除的记录数
*/
async deleteById(id: number): Promise<number> {
if (!this.rdbStore) {
throw new Error('[UserModel] 数据库未初始化');
}
// 构建删除条件(谓词)
const predicates = new relationalStore.RdbPredicates('user_info');
predicates.equalTo('id', id);
try {
const rows = await this.rdbStore.delete(predicates);
console.info(`[UserModel] 删除成功, 影响行数 = ${rows}`);
return rows;
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 删除失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 更新用户信息
* @param user - 包含更新信息的用户对象(必须包含 id)
* @returns 被更新的记录数
*/
async update(user: UserInfo): Promise<number> {
if (!this.rdbStore) {
throw new Error('[UserModel] 数据库未初始化');
}
if (!user.id) {
throw new Error('[UserModel] 更新操作必须提供 id');
}
// 构建更新值桶
const valueBucket: relationalStore.ValuesBucket = {
name: user.name,
email: user.email,
phone: user.phone,
avatar: user.avatar ?? '',
update_time: Date.now()
};
// 构建更新条件
const predicates = new relationalStore.RdbPredicates('user_info');
predicates.equalTo('id', user.id);
try {
const rows = await this.rdbStore.update(valueBucket, predicates);
console.info(`[UserModel] 更新成功, 影响行数 = ${rows}`);
return rows;
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 更新失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 查询所有用户
* @returns 用户信息数组
*/
async queryAll(): Promise<UserInfo[]> {
if (!this.rdbStore) {
throw new Error('[UserModel] 数据库未初始化');
}
// 构建查询谓词
const predicates = new relationalStore.RdbPredicates('user_info');
// 按创建时间降序排列
predicates.orderByDesc('create_time');
try {
// 执行查询
const resultSet = await this.rdbStore.query(predicates);
const users: UserInfo[] = [];
// 遍历结果集
while (resultSet.goToNextRow()) {
const user: UserInfo = {
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
email: resultSet.getString(resultSet.getColumnIndex('email')),
phone: resultSet.getString(resultSet.getColumnIndex('phone')),
avatar: resultSet.getString(resultSet.getColumnIndex('avatar')),
createTime: resultSet.getLong(resultSet.getColumnIndex('create_time')),
updateTime: resultSet.getLong(resultSet.getColumnIndex('update_time'))
};
users.push(user);
}
// 关闭结果集释放资源
resultSet.close();
console.info(`[UserModel] 查询成功, 共 ${users.length} 条记录`);
return users;
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 查询失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 根据 ID 查询单个用户
* @param id - 用户 ID
* @returns 用户信息或 null
*/
async queryById(id: number): Promise<UserInfo | null> {
if (!this.rdbStore) {
throw new Error('[UserModel] 数据库未初始化');
}
const predicates = new relationalStore.RdbPredicates('user_info');
predicates.equalTo('id', id);
try {
const resultSet = await this.rdbStore.query(predicates);
let user: UserInfo | null = null;
if (resultSet.goToNextRow()) {
user = {
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
email: resultSet.getString(resultSet.getColumnIndex('email')),
phone: resultSet.getString(resultSet.getColumnIndex('phone')),
avatar: resultSet.getString(resultSet.getColumnIndex('avatar')),
createTime: resultSet.getLong(resultSet.getColumnIndex('create_time')),
updateTime: resultSet.getLong(resultSet.getColumnIndex('update_time'))
};
}
resultSet.close();
return user;
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 查询失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 根据关键词搜索用户
* 支持按名称、邮箱、手机号模糊匹配
* @param keyword - 搜索关键词
* @returns 匹配的用户数组
*/
async search(keyword: string): Promise<UserInfo[]> {
if (!this.rdbStore) {
throw new Error('[UserModel] 数据库未初始化');
}
const predicates = new relationalStore.RdbPredicates('user_info');
// 使用 OR 组合多个模糊查询条件
predicates
.like('name', `%${keyword}%`)
.or()
.like('email', `%${keyword}%`)
.or()
.like('phone', `%${keyword}%`);
try {
const resultSet = await this.rdbStore.query(predicates);
const users: UserInfo[] = [];
while (resultSet.goToNextRow()) {
users.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
email: resultSet.getString(resultSet.getColumnIndex('email')),
phone: resultSet.getString(resultSet.getColumnIndex('phone')),
avatar: resultSet.getString(resultSet.getColumnIndex('avatar')),
createTime: resultSet.getLong(resultSet.getColumnIndex('create_time')),
updateTime: resultSet.getLong(resultSet.getColumnIndex('update_time'))
});
}
resultSet.close();
return users;
} catch (error) {
const err = error as BusinessError;
console.error(`[UserModel] 搜索失败: ${err.code} - ${err.message}`);
throw err;
}
}
/**
* 关闭数据库连接
* 应在应用退出或不再需要时调用
*/
async close(): Promise<void> {
if (this.rdbStore) {
await this.rdbStore.close();
this.rdbStore = null;
UserModel.instance = null;
console.info('[UserModel] 数据库连接已关闭');
}
}
}
8.2 页面 UI 生成
开发者输入:
帮我生成一个设置页面,包含以下功能模块:
1. 用户信息卡片(头像、昵称、手机号)
2. 功能列表(账号安全、通知设置、隐私设置、语言设置)
3. 关于我们
4. 退出登录按钮
DevEco Code 生成的完整页面代码:
typescript
// ===================================================
// 文件:src/main/ets/pages/SettingsPage.ets
// 描述:应用设置页面,包含用户信息、功能列表和操作按钮
// ===================================================
import router from '@ohos.router';
/**
* 设置项数据结构
*/
interface SettingItem {
icon: Resource; // 图标资源
title: string; // 标题文字
subtitle?: string; // 副标题(可选)
route?: string; // 跳转路由(可选)
showArrow: boolean; // 是否显示右箭头
}
/**
* 设置页面入口组件
* 使用 @Entry 装饰器标记为页面入口
* 使用 @Component 装饰器标记为自定义组件
*/
@Entry
@Component
struct SettingsPage {
// ---- 状态变量 ----
// @State 装饰器:当变量值变化时,自动刷新 UI
@State userNickname: string = '鸿蒙开发者';
@State userPhone: string = '138****8888';
@State userAvatar: string = ''; // 头像 URL,空则显示默认头像
@State isDarkMode: boolean = false;
// 设置项列表数据
@State settingSections: SettingItem[][] = [
// 第一组:账号相关
[
{ icon: $r('app.media.ic_security'), title: '账号安全', subtitle: '已绑定', route: '/pages/AccountSecurity', showArrow: true },
{ icon: $r('app.media.ic_notification'), title: '通知设置', subtitle: '', route: '/pages/NotificationSettings', showArrow: true },
],
// 第二组:偏好设置
[
{ icon: $r('app.media.ic_privacy'), title: '隐私设置', subtitle: '', route: '/pages/PrivacySettings', showArrow: true },
{ icon: $r('app.media.ic_language'), title: '语言设置', subtitle: '简体中文', route: '/pages/LanguageSettings', showArrow: true },
],
// 第三组:其他
[
{ icon: $r('app.media.ic_about'), title: '关于我们', subtitle: 'v1.0.0', route: '/pages/AboutPage', showArrow: true },
]
];
/**
* 页面即将显示时的生命周期回调
* 可在此处加载用户数据
*/
aboutToAppear(): void {
// TODO: 从本地存储或网络加载用户信息
this.loadUserInfo();
}
/**
* 加载用户信息
* 模拟异步加载过程
*/
private async loadUserInfo(): Promise<void> {
try {
// 模拟网络请求延迟
// 实际开发中替换为真实的 API 调用
// const response = await httpClient.get('/api/user/profile');
// this.userNickname = response.data.nickname;
// this.userPhone = response.data.phone;
// this.userAvatar = response.data.avatar;
console.info('[SettingsPage] 用户信息加载完成');
} catch (error) {
console.error('[SettingsPage] 加载用户信息失败');
}
}
/**
* 处理设置项点击事件
* @param item - 被点击的设置项
*/
private handleSettingClick(item: SettingItem): void {
if (item.route) {
router.pushUrl({ url: item.route });
}
}
/**
* 处理退出登录
* 弹出确认对话框,用户确认后清除登录状态并跳转
*/
private handleLogout(): void {
// 使用 AlertDialog 弹出确认框
AlertDialog.show({
title: '退出登录',
message: '确定要退出当前账号吗?',
primaryButton: {
value: '取消',
action: () => {
console.info('[SettingsPage] 用户取消退出');
}
},
secondaryButton: {
value: '退出',
fontColor: '#FF0000',
action: () => {
// TODO: 清除本地存储的登录凭证
// AppStorage.setOrCreate('isLoggedIn', false);
// 跳转到登录页面
router.replaceUrl({ url: '/pages/LoginPage' });
}
}
});
}
/**
* 构建页面 UI
* 使用 ArkTS 声明式语法描述 UI 结构
*/
build() {
// 使用 Scroll 容器实现页面滚动
Scroll() {
// 垂直布局容器
Column() {
// ========== 1. 用户信息卡片 ==========
this.UserInfoCard()
// ========== 2. 功能列表区域 ==========
ForEach(this.settingSections, (section: SettingItem[], sectionIndex: number) => {
this.SettingSection({
items: section
})
// 每组之间添加间距
if (sectionIndex < this.settingSections.length - 1) {
Blank().height(12) // 组间距 12vp
}
}, (section: SettingItem[], index: number) => `section_${index}`)
// ========== 3. 退出登录按钮 ==========
Button('退出登录')
.width('90%')
.height(48)
.fontSize(16)
.fontColor('#FF3B30')
.backgroundColor(Color.Transparent)
.borderRadius(12)
.border({ width: 1, color: '#FF3B30' })
.margin({ top: 40, bottom: 20 })
.onClick(() => this.handleLogout())
// ========== 4. 底部版权信息 ==========
Text('© 2026 HarmonyOS Developer')
.fontSize(12)
.fontColor('#999999')
.margin({ bottom: 30 })
}
.width('100%')
.padding({ left: 16, right: 16 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
/**
* 用户信息卡片组件
* 使用 @Builder 装饰器定义可复用的 UI 构建函数
*/
@Builder
UserInfoCard() {
Row() {
// 头像区域
Stack() {
if (this.userAvatar) {
// 有头像时显示用户头像
Image(this.userAvatar)
.width(64)
.height(64)
.borderRadius(32)
.objectFit(ImageFit.Cover)
} else {
// 无头像时显示默认头像
Column() {
Text(this.userNickname.charAt(0))
.fontSize(24)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
}
.width(64)
.height(64)
.borderRadius(32)
.backgroundColor('#007DFF')
.justifyContent(FlexAlign.Center)
}
}
// 用户信息文字区域
Column() {
Text(this.userNickname)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
Text(this.userPhone)
.fontSize(14)
.fontColor('#666666')
.margin({ top: 4 })
}
.alignItems(HorizontalAlign.Start)
.margin({ left: 16 })
.layoutWeight(1) // 占据剩余空间
// 右箭头
Image($r('app.media.ic_arrow_right'))
.width(20)
.height(20)
.fillColor('#CCCCCC')
}
.width('100%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.margin({ top: 16 })
.shadow({ radius: 4, color: 'rgba(0,0,0,0.05)', offsetY: 2 })
.onClick(() => {
// 点击跳转到个人信息页面
router.pushUrl({ url: '/pages/ProfilePage' });
})
}
/**
* 设置项分组组件
* @param items - 该组包含的设置项列表
*/
@Builder
SettingSection({ items }: { items: SettingItem[] }) {
Column() {
ForEach(items, (item: SettingItem, index: number) => {
Row() {
// 图标
Image(item.icon)
.width(24)
.height(24)
.fillColor('#007DFF')
// 标题
Text(item.title)
.fontSize(16)
.fontColor('#1A1A1A')
.margin({ left: 12 })
.layoutWeight(1)
// 副标题
if (item.subtitle) {
Text(item.subtitle)
.fontSize(14)
.fontColor('#999999')
.margin({ right: 8 })
}
// 右箭头
if (item.showArrow) {
Image($r('app.media.ic_arrow_right'))
.width(16)
.height(16)
.fillColor('#CCCCCC')
}
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.onClick(() => this.handleSettingClick(item))
// 分割线(最后一项不显示)
if (index < items.length - 1) {
Divider()
.strokeWidth(0.5)
.color('#EEEEEE')
.margin({ left: 52 })
}
}, (item: SettingItem, index: number) => `setting_${item.title}_${index}`)
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(12)
.margin({ top: 12 })
}
}
8.3 万能卡片生成
详见第十章实战四。
8.4 代码重构与优化
DevEco Code 能够识别代码中的"坏味道"并自动重构:
请分析以下代码并进行重构优化:
1. 提取重复代码为公共组件
2. 优化状态管理
3. 提升列表渲染性能
8.5 Bug 诊断与修复
将编译错误粘贴给 DevEco Code,它会:
- 读取相关文件
- 分析错误根因
- 给出修复方案
- 直接修改代码(需确认)
8.6 工程辅助与构建管理
- ohpm 依赖管理
- module.json5 权限配置
- Hvigor 构建脚本
- HAR/HSP 模块管理
8.7 知识问答与文档查询
基于 HarmonyOS 官方文档训练的精准问答。
九、斜杠命令与快捷键大全
9.1 高频必备命令
| 命令 | 功能 | 使用频率 |
|---|---|---|
/help |
显示帮助信息 | ⭐⭐⭐⭐⭐ |
/model |
切换 AI 模型 | ⭐⭐⭐⭐⭐ |
/clear |
清空对话历史 | ⭐⭐⭐⭐⭐ |
/compact |
压缩对话上下文 | ⭐⭐⭐⭐ |
/exit |
退出 DevEco Code | ⭐⭐⭐⭐ |
/cost |
Token 使用统计 | ⭐⭐⭐ |
9.2 会话与上下文管理命令
| 命令 | 功能 | 详细说明 |
|---|---|---|
/clear |
清空对话 | 释放上下文空间,开始新任务 |
/compact [指令] |
压缩上下文 | 保留关键信息,减少 Token 消耗 |
/status |
查看状态 | 显示当前模型、项目路径、Token 用量 |
/diff |
查看变更 | Git diff 风格显示所有文件修改 |
/undo |
撤销修改 | 可多次执行,逐步回退 |
/add-dir <路径> |
添加目录 | 让 AI 访问额外目录 |
9.3 模型与配置命令
| 命令 | 功能 |
|---|---|
/model |
切换模型(弹出选择列表) |
/config |
查看/修改配置 |
/cost |
Token 使用统计与费用 |
9.4 项目级命令
| 命令 | 功能 |
|---|---|
switch_cwd |
切换项目工作目录 |
/init |
分析项目结构,生成项目记忆文件 |
9.5 调试与诊断命令
| 命令 | 功能 |
|---|---|
/doctor |
检查安装健康状态 |
/bug |
向开发团队报告 Bug |
9.6 快捷键一览
| 快捷键 | 功能 | 说明 |
|---|---|---|
Enter |
发送消息 | 提交当前输入 |
Shift+Enter |
换行 | 多行输入模式 |
Ctrl+C |
中断操作 | 终止 AI 生成 |
Ctrl+D |
退出 | 等同于 /exit |
↑ / ↓ |
浏览历史 | 浏览之前输入的消息 |
Tab |
自动补全 | 补全命令或文件路径 |
Esc |
取消 | 取消当前输入 |
9.7 MacOS 专属快捷键
在 MacOS 终端中,还有一些额外的快捷键可以提升效率:
| 快捷键 | 功能 |
|---|---|
Cmd+C |
复制(iTerm2 中) |
Cmd+V |
粘贴 |
Cmd+K |
清屏(iTerm2) |
Cmd+T |
新标签页(iTerm2) |
Cmd+W |
关闭标签页 |
Cmd+D |
水平分屏(iTerm2) |
Cmd+Shift+D |
垂直分屏 |
Ctrl+A |
跳到行首 |
Ctrl+E |
跳到行尾 |
Ctrl+U |
删除光标前所有内容 |
Option+←/→ |
按词移动光标 |
十、实战案例:使用 DevEco Code 开发鸿蒙应用
10.1 实战一:从零创建 HarmonyOS 项目
步骤 1:在 DevEco Studio 中创建 Empty Ability 项目
步骤 2:打开终端并启动 DevEco Code
bash
cd ~/HarmonyOSProjects/MyFirstApp
deveco
步骤 3:初始化项目记忆
/init
步骤 4:让 AI 生成首页
请帮我修改 Index 页面,创建一个待办事项应用:
1. 顶部标题栏显示"我的待办"
2. 输入框 + 添加按钮
3. 待办列表(支持勾选完成、左滑删除)
4. 底部显示完成进度
DevEco Code 生成完整代码并写入文件,你确认后切换到 DevEco Studio 预览。
10.2 实战二:AI 生成电商首页 UI(完整代码)
开发者输入:
帮我生成一个电商应用首页,包含:搜索栏、轮播广告、分类导航、商品瀑布流
生成的完整代码:
typescript
// ===================================================
// 文件:src/main/ets/pages/ECommerceHome.ets
// 描述:电商应用首页,包含搜索、轮播、分类、商品列表
// ===================================================
import router from '@ohos.router';
/**
* 商品数据接口
*/
interface ProductItem {
id: number; // 商品 ID
title: string; // 商品标题
price: number; // 价格(元)
originalPrice: number; // 原价
imageUrl: string; // 商品图片 URL
sales: number; // 销量
shopName: string; // 店铺名称
}
/**
* 分类导航数据接口
*/
interface CategoryItem {
id: number; // 分类 ID
name: string; // 分类名称
icon: Resource; // 分类图标
}
/**
* 轮播广告数据接口
*/
interface BannerItem {
id: number; // 广告 ID
imageUrl: string; // 广告图片 URL
linkUrl: string; // 点击跳转链接
}
/**
* 电商首页入口组件
*/
@Entry
@Component
struct ECommerceHome {
// ---- 状态管理 ----
@State searchText: string = ''; // 搜索框文字
@State currentBannerIndex: number = 0; // 当前轮播索引
@State productList: ProductItem[] = []; // 商品列表
@State isLoading: boolean = false; // 加载中状态
@State isRefreshing: boolean = false; // 下拉刷新状态
@State currentTabIndex: number = 0; // 当前 Tab 索引
// Swiper 控制器
private swiperController: SwiperController = new SwiperController();
// ---- 模拟数据 ----
// 轮播广告数据
@State bannerList: BannerItem[] = [
{ id: 1, imageUrl: 'https://placeholder.com/banner1.jpg', linkUrl: '' },
{ id: 2, imageUrl: 'https://placeholder.com/banner2.jpg', linkUrl: '' },
{ id: 3, imageUrl: 'https://placeholder.com/banner3.jpg', linkUrl: '' },
];
// 分类导航数据(4列2行 = 8个分类)
@State categoryList: CategoryItem[] = [
{ id: 1, name: '新品首发', icon: $r('app.media.ic_new') },
{ id: 2, name: '限时秒杀', icon: $r('app.media.ic_flash') },
{ id: 3, name: '品牌特卖', icon: $r('app.media.ic_brand') },
{ id: 4, name: '充值中心', icon: $r('app.media.ic_recharge') },
{ id: 5, name: '领券中心', icon: $r('app.media.ic_coupon') },
{ id: 6, name: '拼团优惠', icon: $r('app.media.ic_group') },
{ id: 7, name: '积分商城', icon: $r('app.media.ic_points') },
{ id: 8, name: '更多分类', icon: $r('app.media.ic_more') },
];
// Tab 标签数据
private tabTitles: string[] = ['推荐', '数码', '服饰', '美食', '家居', '运动'];
/**
* 组件即将出现时的生命周期回调
* 加载初始数据
*/
aboutToAppear(): void {
this.loadProducts();
}
/**
* 加载商品列表数据
* 模拟网络请求
*/
private async loadProducts(): Promise<void> {
this.isLoading = true;
try {
// 模拟网络延迟 500ms
await new Promise<void>((resolve) => setTimeout(resolve, 500));
// 模拟商品数据
const mockProducts: ProductItem[] = [
{
id: 1,
title: 'HUAWEI MatePad Pro 13.2英寸 平板电脑',
price: 4299,
originalPrice: 4999,
imageUrl: 'https://placeholder.com/product1.jpg',
sales: 12580,
shopName: '华为官方旗舰店'
},
{
id: 2,
title: 'HUAWEI FreeBuds Pro 3 真无线蓝牙耳机',
price: 1199,
originalPrice: 1499,
imageUrl: 'https://placeholder.com/product2.jpg',
sales: 35600,
shopName: '华为官方旗舰店'
},
{
id: 3,
title: '鸿蒙智联 智能台灯 Pro 护眼学习灯',
price: 299,
originalPrice: 399,
imageUrl: 'https://placeholder.com/product3.jpg',
sales: 8920,
shopName: '智能家居旗舰店'
},
{
id: 4,
title: 'HarmonyOS 开发者定制机械键盘 87键',
price: 599,
originalPrice: 799,
imageUrl: 'https://placeholder.com/product4.jpg',
sales: 2340,
shopName: '极客外设店'
},
];
this.productList = mockProducts;
} catch (error) {
console.error('[ECommerceHome] 加载商品失败');
} finally {
this.isLoading = false;
}
}
/**
* 下拉刷新处理
*/
private async onRefresh(): Promise<void> {
this.isRefreshing = true;
await this.loadProducts();
this.isRefreshing = false;
}
/**
* 格式化销量显示
* @param sales - 原始销量数字
* @returns 格式化后的字符串(如 "1.2万")
*/
private formatSales(sales: number): string {
if (sales >= 10000) {
return (sales / 10000).toFixed(1) + '万';
}
return sales.toString();
}
/**
* 格式化价格显示
* @param price - 价格数字
* @returns 保留两位小数的字符串
*/
private formatPrice(price: number): string {
return price.toFixed(2);
}
/**
* 构建页面主体 UI
*/
build() {
Column() {
// ========== 1. 顶部搜索栏 ==========
this.SearchBar()
// ========== 2. 可滚动内容区域 ==========
Refresh({ refreshing: this.isRefreshing }) {
Scroll() {
Column() {
// 轮播广告
this.BannerSection()
// 分类导航
this.CategorySection()
// Tab 标签 + 商品列表
this.ProductSection()
}
.width('100%')
}
.layoutWeight(1)
.scrollBar(BarState.Off)
}
.onRefreshing(() => this.onRefresh())
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
/**
* 搜索栏组件
*/
@Builder
SearchBar() {
Row() {
// 搜索输入框
Row() {
Image($r('app.media.ic_search'))
.width(18)
.height(18)
.fillColor('#999999')
.margin({ left: 12 })
TextInput({ placeholder: '搜索商品、品牌、店铺', text: this.searchText })
.layoutWeight(1)
.fontSize(14)
.backgroundColor(Color.Transparent)
.onChange((value: string) => {
this.searchText = value;
})
.onSubmit(() => {
// 跳转到搜索结果页
router.pushUrl({
url: '/pages/SearchResultPage',
params: { keyword: this.searchText }
});
})
}
.height(36)
.backgroundColor('#F0F0F0')
.borderRadius(18)
.layoutWeight(1)
// 搜索按钮
Text('搜索')
.fontSize(14)
.fontColor('#007DFF')
.margin({ left: 12 })
.onClick(() => {
router.pushUrl({
url: '/pages/SearchResultPage',
params: { keyword: this.searchText }
});
})
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor(Color.White)
}
/**
* 轮播广告组件
*/
@Builder
BannerSection() {
Swiper(this.swiperController) {
ForEach(this.bannerList, (banner: BannerItem) => {
// 轮播图片
Stack() {
Image(banner.imageUrl)
.width('100%')
.height('100%')
.objectFit(ImageFit.Cover)
.borderRadius(12)
// 渐变遮罩(底部)
Column()
.width('100%')
.height(40)
.linearGradient({
direction: GradientDirection.Bottom,
colors: [['rgba(0,0,0,0)', 0], ['rgba(0,0,0,0.3)', 1]]
})
.position({ bottom: 0 })
.borderRadius({ bottomLeft: 12, bottomRight: 12 })
}
.width('100%')
.height(180)
}, (banner: BannerItem) => `banner_${banner.id}`)
}
.width('100%')
.height(180)
.autoPlay(true) // 自动播放
.interval(3000) // 切换间隔 3 秒
.indicator(true) // 显示指示器
.loop(true) // 循环播放
.cachedCount(1) // 预加载数量
.borderRadius(12)
.margin({ top: 12, left: 16, right: 16 })
.onChange((index: number) => {
this.currentBannerIndex = index;
})
}
/**
* 分类导航组件
* 4列2行网格布局
*/
@Builder
CategorySection() {
Column() {
Grid() {
ForEach(this.categoryList, (category: CategoryItem) => {
GridItem() {
Column() {
// 分类图标
Image(category.icon)
.width(40)
.height(40)
.objectFit(ImageFit.Contain)
// 分类名称
Text(category.name)
.fontSize(12)
.fontColor('#333333')
.margin({ top: 6 })
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.justifyContent(FlexAlign.Center)
.onClick(() => {
// 跳转到分类详情页
router.pushUrl({
url: '/pages/CategoryPage',
params: { categoryId: category.id, categoryName: category.name }
});
})
}
}, (category: CategoryItem) => `category_${category.id}`)
}
.columnsTemplate('1fr 1fr 1fr 1fr') // 4列等宽
.rowsGap(12) // 行间距
.columnsGap(8) // 列间距
.height(160) // 固定高度(2行)
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
.margin({ top: 12, left: 16, right: 16 })
}
/**
* 商品列表区域
* 包含 Tab 标签切换和瀑布流商品列表
*/
@Builder
ProductSection() {
Column() {
// ---- Tab 标签栏 ----
Scroll() {
Row() {
ForEach(this.tabTitles, (title: string, index: number) => {
Column() {
Text(title)
.fontSize(14)
.fontWeight(this.currentTabIndex === index ? FontWeight.Bold : FontWeight.Normal)
.fontColor(this.currentTabIndex === index ? '#007DFF' : '#666666')
// 选中标签下划线
if (this.currentTabIndex === index) {
Row()
.width(20)
.height(3)
.backgroundColor('#007DFF')
.borderRadius(1.5)
.margin({ top: 4 })
}
}
.padding({ left: 12, right: 12 })
.onClick(() => {
this.currentTabIndex = index;
// TODO: 根据 Tab 切换加载不同分类的商品
this.loadProducts();
})
}, (title: string, index: number) => `tab_${title}_${index}`)
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
.height(44)
.padding({ left: 4 })
// ---- 商品瀑布流列表 ----
// 使用 WaterFlow 实现瀑布流布局
WaterFlow() {
ForEach(this.productList, (product: ProductItem) => {
FlowItem() {
this.ProductCard({ product: product })
}
}, (product: ProductItem) => `product_${product.id}`)
}
.columnsTemplate('1fr 1fr') // 两列
.columnsGap(8)
.rowsGap(8)
.padding({ left: 16, right: 16 })
.width('100%')
.layoutWeight(1)
// ---- 加载状态 ----
if (this.isLoading) {
Row() {
LoadingProgress()
.width(24)
.height(24)
.color('#007DFF')
Text('加载中...')
.fontSize(14)
.fontColor('#999999')
.margin({ left: 8 })
}
.width('100%')
.justifyContent(FlexAlign.Center)
.padding(20)
}
}
.margin({ top: 12 })
}
/**
* 商品卡片组件
* @param product - 商品数据
*/
@Builder
ProductCard({ product }: { product: ProductItem }) {
Column() {
// 商品图片
Image(product.imageUrl)
.width('100%')
.aspectRatio(1) // 正方形图片
.objectFit(ImageFit.Cover)
.borderRadius({ topLeft: 8, topRight: 8 })
// 商品信息区域
Column() {
// 商品标题(最多2行)
Text(product.title)
.fontSize(13)
.fontColor('#333333')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.lineHeight(18)
// 价格行
Row() {
// 现价
Text(`¥${this.formatPrice(product.price)}`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#FF4D4F')
// 原价(划线)
if (product.originalPrice > product.price) {
Text(`¥${this.formatPrice(product.originalPrice)}`)
.fontSize(12)
.fontColor('#CCCCCC')
.decoration({ type: TextDecorationType.LineThrough })
.margin({ left: 6 })
}
}
.margin({ top: 8 })
.alignItems(VerticalAlign.Bottom)
// 底部信息行
Row() {
Text(product.shopName)
.fontSize(11)
.fontColor('#999999')
.layoutWeight(1)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(`${this.formatSales(product.sales)}人付款`)
.fontSize(11)
.fontColor('#999999')
}
.width('100%')
.margin({ top: 6 })
}
.padding(10)
}
.backgroundColor(Color.White)
.borderRadius(8)
.shadow({ radius: 2, color: 'rgba(0,0,0,0.04)', offsetY: 1 })
.onClick(() => {
// 跳转到商品详情页
router.pushUrl({
url: '/pages/ProductDetailPage',
params: { productId: product.id }
});
})
}
}
10.3 实战三:网络请求与数据绑定(完整代码)
typescript
// ===================================================
// 文件:src/main/ets/pages/NewsListPage.ets
// 描述:新闻列表页面,展示网络请求、数据绑定、下拉刷新、
// 上拉加载更多、错误处理等完整功能
// ===================================================
import http from '@ohos.net.http';
import router from '@ohos.router';
/**
* 新闻数据接口
*/
interface NewsItem {
id: number; // 新闻 ID
title: string; // 标题
summary: string; // 摘要
coverUrl: string; // 封面图片 URL
source: string; // 新闻来源
publishTime: string; // 发布时间
category: string; // 分类
}
/**
* API 响应数据结构
*/
interface ApiResponse {
code: number; // 响应码(0 表示成功)
message: string; // 响应消息
data: {
list: NewsItem[]; // 新闻列表
total: number; // 总数
hasMore: boolean; // 是否有更多
};
}
/**
* 页面状态枚举
* 用于统一管理页面的不同状态
*/
enum PageState {
LOADING, // 首次加载中
SUCCESS, // 加载成功
ERROR, // 加载失败
EMPTY // 数据为空
}
/**
* 新闻列表页面
*/
@Entry
@Component
struct NewsListPage {
// ---- 状态变量 ----
@State newsList: NewsItem[] = []; // 新闻列表数据
@State pageState: PageState = PageState.LOADING; // 页面状态
@State isRefreshing: boolean = false; // 下拉刷新状态
@State isLoadingMore: boolean = false; // 加载更多状态
@State hasMore: boolean = true; // 是否有更多数据
@State currentPage: number = 1; // 当前页码
@State errorMessage: string = ''; // 错误消息
// 每页数据量
private readonly PAGE_SIZE: number = 10;
// API 地址
private readonly API_URL: string = 'https://api.example.com/news';
/**
* 页面生命周期:组件即将出现
* 自动加载第一页数据
*/
aboutToAppear(): void {
this.fetchNews(true);
}
/**
* 获取新闻列表数据
* @param isFirstPage - 是否请求第一页(决定是刷新还是追加)
*/
private async fetchNews(isFirstPage: boolean): Promise<void> {
// 如果是第一页,设置加载状态
if (isFirstPage) {
this.pageState = PageState.LOADING;
this.currentPage = 1;
} else {
this.isLoadingMore = true;
}
try {
// 创建 HTTP 请求对象
const httpRequest = http.createHttp();
// 构建请求 URL(附带分页参数)
const url = `${this.API_URL}?page=${this.currentPage}&size=${this.PAGE_SIZE}`;
// 发起 GET 请求
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json',
// 实际项目中在此处添加认证 Token
// 'Authorization': `Bearer ${token}`
},
connectTimeout: 10000, // 连接超时 10 秒
readTimeout: 15000, // 读取超时 15 秒
});
// 销毁请求对象,释放资源
httpRequest.destroy();
// 检查 HTTP 状态码
if (response.responseCode === http.ResponseCode.OK) {
// 解析响应数据
const result = JSON.parse(response.result as string) as ApiResponse;
if (result.code === 0) {
if (isFirstPage) {
// 第一页:替换列表数据
this.newsList = result.data.list;
} else {
// 非第一页:追加到列表末尾
this.newsList = [...this.newsList, ...result.data.list];
}
// 更新分页状态
this.hasMore = result.data.hasMore;
this.currentPage++;
// 更新页面状态
if (this.newsList.length === 0) {
this.pageState = PageState.EMPTY;
} else {
this.pageState = PageState.SUCCESS;
}
} else {
// 业务错误
throw new Error(result.message || '请求失败');
}
} else {
// HTTP 错误
throw new Error(`HTTP Error: ${response.responseCode}`);
}
} catch (error) {
// 错误处理
const err = error as Error;
this.errorMessage = err.message || '网络异常,请稍后重试';
// 如果是第一页加载失败,显示错误页面
if (isFirstPage && this.newsList.length === 0) {
this.pageState = PageState.ERROR;
}
console.error(`[NewsListPage] 请求失败: ${this.errorMessage}`);
} finally {
// 无论成功失败,重置刷新/加载状态
this.isRefreshing = false;
this.isLoadingMore = false;
}
}
/**
* 下拉刷新处理
*/
private async onRefresh(): Promise<void> {
this.isRefreshing = true;
this.hasMore = true;
await this.fetchNews(true);
}
/**
* 上拉加载更多处理
*/
private async onLoadMore(): Promise<void> {
if (!this.hasMore || this.isLoadingMore) {
return; // 没有更多数据或正在加载中,跳过
}
await this.fetchNews(false);
}
/**
* 格式化时间显示
* @param timeStr - ISO 时间字符串
* @returns 友好的时间显示(如 "3分钟前"、"2小时前")
*/
private formatTime(timeStr: string): string {
const now = Date.now();
const time = new Date(timeStr).getTime();
const diff = now - time;
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (minutes < 1) return '刚刚';
if (minutes < 60) return `${minutes}分钟前`;
if (hours < 24) return `${hours}小时前`;
if (days < 7) return `${days}天前`;
return timeStr.substring(0, 10); // 显示日期
}
/**
* 构建页面主体
*/
build() {
Column() {
// 顶部标题栏
this.TitleBar()
// 根据页面状态显示不同内容
if (this.pageState === PageState.LOADING) {
// 首次加载中
this.LoadingView()
} else if (this.pageState === PageState.ERROR) {
// 加载失败
this.ErrorView()
} else if (this.pageState === PageState.EMPTY) {
// 数据为空
this.EmptyView()
} else {
// 正常显示列表
this.NewsList()
}
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
/**
* 标题栏组件
*/
@Builder
TitleBar() {
Row() {
Text('新闻资讯')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Start)
}
/**
* 新闻列表组件
*/
@Builder
NewsList() {
Refresh({ refreshing: this.isRefreshing }) {
List() {
ForEach(this.newsList, (news: NewsItem) => {
ListItem() {
this.NewsCard({ news: news })
}
}, (news: NewsItem) => `news_${news.id}`)
// 底部加载更多提示
ListItem() {
Row() {
if (this.isLoadingMore) {
LoadingProgress()
.width(20)
.height(20)
.color('#999999')
Text('加载中...')
.fontSize(13)
.fontColor('#999999')
.margin({ left: 8 })
} else if (!this.hasMore) {
Text('--- 已经到底了 ---')
.fontSize(13)
.fontColor('#CCCCCC')
}
}
.width('100%')
.justifyContent(FlexAlign.Center)
.padding(20)
}
}
.width('100%')
.divider({ strokeWidth: 0 })
.scrollBar(BarState.Off)
.onReachEnd(() => this.onLoadMore())
}
.onRefreshing(() => this.onRefresh())
.layoutWeight(1)
}
/**
* 新闻卡片组件
*/
@Builder
NewsCard({ news }: { news: NewsItem }) {
Row() {
// 文字内容区域
Column() {
// 标题
Text(news.title)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#1A1A1A')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.lineHeight(22)
// 摘要
Text(news.summary)
.fontSize(13)
.fontColor('#999999')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ top: 6 })
// 底部信息行
Row() {
Text(news.source)
.fontSize(12)
.fontColor('#007DFF')
Text(' · ')
.fontSize(12)
.fontColor('#CCCCCC')
Text(this.formatTime(news.publishTime))
.fontSize(12)
.fontColor('#CCCCCC')
}
.margin({ top: 8 })
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
// 封面图片
Image(news.coverUrl)
.width(120)
.height(80)
.objectFit(ImageFit.Cover)
.borderRadius(8)
.margin({ left: 12 })
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.margin({ top: 1 })
.onClick(() => {
router.pushUrl({
url: '/pages/NewsDetailPage',
params: { newsId: news.id }
});
})
}
/**
* 加载中视图
*/
@Builder
LoadingView() {
Column() {
LoadingProgress()
.width(48)
.height(48)
.color('#007DFF')
Text('加载中...')
.fontSize(14)
.fontColor('#999999')
.margin({ top: 12 })
}
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
}
/**
* 错误视图
*/
@Builder
ErrorView() {
Column() {
Image($r('app.media.ic_error'))
.width(80)
.height(80)
Text(this.errorMessage)
.fontSize(14)
.fontColor('#666666')
.margin({ top: 16 })
.textAlign(TextAlign.Center)
Button('重新加载')
.fontSize(14)
.fontColor(Color.White)
.backgroundColor('#007DFF')
.borderRadius(20)
.width(120)
.height(40)
.margin({ top: 20 })
.onClick(() => this.fetchNews(true))
}
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
}
/**
* 空数据视图
*/
@Builder
EmptyView() {
Column() {
Image($r('app.media.ic_empty'))
.width(100)
.height(100)
Text('暂无新闻')
.fontSize(16)
.fontColor('#999999')
.margin({ top: 16 })
Button('刷新')
.fontSize(14)
.fontColor('#007DFF')
.backgroundColor(Color.Transparent)
.border({ width: 1, color: '#007DFF' })
.borderRadius(20)
.width(100)
.height(36)
.margin({ top: 16 })
.onClick(() => this.fetchNews(true))
}
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
}
}
10.4 实战四:万能卡片开发(完整代码)
typescript
// ===================================================
// 文件:src/main/ets/widget/WeatherWidget.ets
// 描述:2×2 规格天气万能卡片
// 展示今日天气信息,支持定时更新
// ===================================================
import { formBindingData, FormExtensionAbility } from '@kit.FormKit';
/**
* 天气数据接口
*/
interface WeatherData {
city: string; // 城市名称
temperature: number; // 当前温度
weatherIcon: string; // 天气图标名称
weatherDesc: string; // 天气描述(晴、多云、雨等)
highTemp: number; // 最高温度
lowTemp: number; // 最低温度
aqi: number; // 空气质量指数
aqiLevel: string; // 空气质量等级
updateTime: string; // 更新时间
}
/**
* 天气万能卡片表单扩展能力
*
* 万能卡片通过 FormExtensionAbility 生命周期管理:
* - onAddForm: 卡片首次创建时调用
* - onUpdateForm: 卡片更新时调用(定时或手动)
* - onCastToNormalForm: 临时卡片转常态卡片时调用
* - onRemoveForm: 卡片被删除时调用
*/
export default class WeatherWidget extends FormExtensionAbility {
/**
* 卡片创建时的回调
* 初始化卡片数据并返回
* @returns 卡片表单数据
*/
onAddForm(): formBindingData.FormBindingData {
console.info('[WeatherWidget] onAddForm 被调用');
// 获取天气数据
const weatherData = this.getWeatherData();
// 构建卡片数据
const formData = {
city: weatherData.city,
temperature: `${weatherData.temperature}°`,
weatherDesc: weatherData.weatherDesc,
weatherIcon: this.getWeatherIconResource(weatherData.weatherIcon),
highLow: `${weatherData.highTemp}° / ${weatherData.lowTemp}°`,
aqi: `${weatherData.aqi} ${weatherData.aqiLevel}`,
updateTime: weatherData.updateTime
};
// 返回表单绑定数据
return formBindingData.createFormBindingData(formData);
}
/**
* 卡片更新时的回调
* 系统会按照配置的更新策略定时调用此方法
* 也可以通过 PostEvent 手动触发更新
* @returns 更新后的卡片数据
*/
onUpdateForm(): formBindingData.FormBindingData {
console.info('[WeatherWidget] onUpdateForm 被调用');
// 重新获取最新天气数据
const weatherData = this.getWeatherData();
const formData = {
city: weatherData.city,
temperature: `${weatherData.temperature}°`,
weatherDesc: weatherData.weatherDesc,
weatherIcon: this.getWeatherIconResource(weatherData.weatherIcon),
highLow: `${weatherData.highTemp}° / ${weatherData.lowTemp}°`,
aqi: `${weatherData.aqi} ${weatherData.aqiLevel}`,
updateTime: weatherData.updateTime
};
return formBindingData.createFormBindingData(formData);
}
/**
* 获取天气数据
* 实际开发中应调用天气 API
* 此处使用模拟数据
* @returns 天气数据对象
*/
private getWeatherData(): WeatherData {
// TODO: 替换为真实的天气 API 调用
// 例如:调用和风天气 API 或华为天气服务
return {
city: '北京',
temperature: 28,
weatherIcon: 'sunny',
weatherDesc: '晴',
highTemp: 32,
lowTemp: 22,
aqi: 75,
aqiLevel: '良',
updateTime: new Date().toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
})
};
}
/**
* 根据天气类型获取对应的图标资源路径
* @param iconName - 天气类型标识
* @returns 图标资源路径
*/
private getWeatherIconResource(iconName: string): string {
const iconMap: Record<string, string> = {
'sunny': '/media/weather_sunny.png',
'cloudy': '/media/weather_cloudy.png',
'rainy': '/media/weather_rainy.png',
'snowy': '/media/weather_snowy.png',
'foggy': '/media/weather_foggy.png',
'thunder': '/media/weather_thunder.png'
};
return iconMap[iconName] || iconMap['sunny'];
}
}
对应的卡片 UI 模板文件:
json
// ===================================================
// 文件:src/main/resources/base/profile/form_config.json
// 描述:万能卡片配置文件
// ===================================================
{
"forms": [
{
"name": "WeatherWidget",
"displayName": "今日天气",
"description": "显示当前城市的天气信息",
"src": "./ets/widget/WeatherWidget.ets",
"uiSyntax": "arkts",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",
"isDynamic": true,
"isDefault": true,
"updateEnabled": true,
"scheduledUpdateTime": "08:00",
"updateDuration": 1,
"defaultDimension": "2*2",
"supportDimensions": ["2*2", "2*4", "4*4"]
}
]
}
卡片 UI 页面文件:
typescript
// ===================================================
// 文件:src/main/ets/widget/pages/WeatherWidgetCard.ets
// 描述:天气卡片的 UI 渲染页面(2×2 规格)
// ===================================================
/**
* 天气卡片 UI 组件
*
* 卡片 UI 与普通页面有以下区别:
* 1. 不能使用 @Entry 装饰器
* 2. 不支持复杂的交互事件
* 3. 样式和 API 有部分限制
* 4. 通过 postCardAction 发送事件
*/
@Component
struct WeatherWidgetCard {
// 从 FormExtensionAbility 传递的数据
@StorageProp('city') city: string = '北京';
@StorageProp('temperature') temperature: string = '28°';
@StorageProp('weatherDesc') weatherDesc: string = '晴';
@StorageProp('highLow') highLow: string = '32° / 22°';
@StorageProp('aqi') aqi: string = '75 良';
@StorageProp('updateTime') updateTime: string = '12:00';
build() {
Column() {
// 第一行:城市和天气描述
Row() {
Text(this.city)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
Blank()
Text(this.weatherDesc)
.fontSize(12)
.fontColor('#666666')
}
.width('100%')
// 第二行:温度大字
Row() {
Text(this.temperature)
.fontSize(36)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
// 天气图标
Image($r('app.media.weather_sunny'))
.width(32)
.height(32)
.margin({ left: 8 })
}
.width('100%')
.margin({ top: 8 })
// 第三行:最高/最低温度
Text(this.highLow)
.fontSize(12)
.fontColor('#999999')
.margin({ top: 4 })
// 第四行:空气质量和更新时间
Row() {
Text(`AQI ${this.aqi}`)
.fontSize(11)
.fontColor('#4CAF50')
Blank()
Text(this.updateTime)
.fontSize(11)
.fontColor('#CCCCCC')
}
.width('100%')
.margin({ top: 8 })
}
.width('100%')
.height('100%')
.padding(16)
.justifyContent(FlexAlign.SpaceBetween)
.backgroundColor(Color.White)
.borderRadius(16)
.onClick(() => {
// 点击卡片跳转到天气详情页面
postCardAction(this, {
action: 'router',
bundleName: 'com.example.weather',
abilityName: 'EntryAbility',
url: 'pages/WeatherDetailPage'
});
})
}
}
10.5 实战五:Bug 排查与修复
场景:编译报错
请帮我修复以下编译错误:
ERROR: ArkTS:ERROR File: src/main/ets/pages/Profile.ets:35:12
Message: The 'this' context of type 'Profile' is not assignable
to method's 'this' of type 'object'.
ERROR: ArkTS:ERROR File: src/main/ets/pages/Profile.ets:48:5
Message: Property 'fetchUserProfile' does not exist on type 'Profile'.
DevEco Code 分析并修复:
它会读取文件,识别问题(this 上下文丢失,方法拼写错误),然后直接修改代码。
10.6 实战六:代码重构与性能优化
场景:列表滚动卡顿
我的 ProductList.ets 页面在展示超过 200 条商品时滚动卡顿,
请帮我分析并优化性能。
DevEco Code 的优化方案:
- 将
ForEach替换为LazyForEach - 创建
IDataSource实现类 - 优化图片加载(使用缓存和占位图)
- 减少不必要的组件嵌套
- 使用
@Reusable装饰器复用组件
十一、与 DevEco Studio 协同工作
11.1 DevEco Studio MacOS 版安装
下载地址:https://developer.huawei.com/consumer/cn/deveco-studio/
Apple Silicon 版本:华为提供专门的 Apple Silicon 版本,性能显著优于 Rosetta 翻译运行的 Intel 版本。下载时选择 "Mac(Arm)" 版本。
安装步骤:
- 下载
.dmg安装包 - 双击打开 DMG 文件
- 将 DevEco Studio 拖拽到 Applications 文件夹
- 首次打开时,MacOS 会提示"来自互联网的应用",点击"打开"
如果提示"无法验证开发者":
bash
# 移除隔离属性
xattr -cr /Applications/DevEco-Studio.app
11.2 双工具协同工作流
┌──────────────────────┐ ┌──────────────────────┐
│ DevEco Code │ │ DevEco Studio │
│ (终端 AI Agent) │ │ (图形化 IDE) │
├──────────────────────┤ ├──────────────────────┤
│ • 需求分析 │────▶│ • 代码审查 │
│ • 代码生成 │ │ • Previewer 预览 │
│ • Bug 修复 │ │ • 模拟器/真机调试 │
│ • 重构优化 │ │ • 性能分析 │
│ • 知识问答 │ │ • 签名打包 │
│ • 构建辅助 │◀────│ • Profiler 分析 │
└──────────────────────┘ └──────────────────────┘
11.3 项目路径切换
switch_cwd ~/HarmonyOSProjects/AnotherApp
11.4 编译、签名与真机调试配合
- DevEco Code:修复编译错误、配置签名参数、生成构建脚本
- DevEco Studio:执行编译、管理证书、连接真机调试
11.5 hdc 工具链配置
hdc(HarmonyOS Device Connector)是鸿蒙设备连接工具,DevEco Code 可以帮你生成和管理 hdc 命令:
bash
# 查看已连接设备
hdc list targets
# 安装应用到设备
hdc install -r entry/build/default/outputs/default/entry-default-signed.hap
# 启动应用
hdc shell aa start -a EntryAbility -b com.example.myapp
# 查看日志
hdc shell hilog | grep "MyApp"
# 截图
hdc shell snapshot_display -f /data/local/tmp/screenshot.png
hdc file recv /data/local/tmp/screenshot.png ~/Desktop/
十二、高级配置与自定义
12.1 配置文件目录结构(MacOS 路径)
~/.deveco/
├── data.db # 本地 SQLite 数据库
├── ai/
│ ├── config.json # 模型配置文件
│ ├── prompts/ # 自定义提示词
│ │ ├── system_prompt.md # 系统提示词
│ │ └── code_style.md # 代码风格模板
│ ├── history/ # 对话历史
│ │ ├── session_20260715.json # 按日期存储
│ │ └── session_20260716.json
│ └── memory.md # 全局记忆文件
├── auth/
│ └── credentials.json # 加密的登录凭证
├── cache/
│ ├── models/ # 模型缓存
│ └── projects/ # 项目索引缓存
└── logs/
└── deveco-code.log # 运行日志
12.2 自定义 Agent 行为与记忆文件
全局记忆文件 ~/.deveco/ai/memory.md:
markdown
# 全局开发偏好
## 代码风格
- 使用 2 空格缩进
- 组件名 PascalCase,变量名 camelCase
- 所有公开 API 必须添加 JSDoc 注释
- import 语句按模块类型分组排列
## 架构偏好
- 使用 Stage 模型
- 页面文件放 pages/ 目录
- 公共组件放 components/ 目录
- 工具类放 utils/ 目录
- 数据模型放 model/ 目录
## 技术要求
- 列表超过 50 项使用 LazyForEach
- 网络请求统一封装在 HttpClient 中
- 使用 AppStorage 管理全局状态
- 所有异步操作使用 async/await
项目级记忆文件 项目根目录/.deveco-rules.md:
markdown
# 项目:电商应用 EShop
## 技术栈
- ArkTS + Stage 模型
- @ohos/axios 网络请求
- @ohos/data_relationalStore 本地存储
## 模块结构
- entry: 主模块
- common: 公共组件库 (HAR)
- network: 网络层 (HAR)
- storage: 数据存储层 (HAR)
## 编码规范
- API 地址统一在 config/ApiConfig.ets 中管理
- 页面路由统一在 router/RouterMap.ets 中注册
- 主题色:#FF6B00(橙色)
12.3 MCP(Model Context Protocol)扩展
MCP 允许你接入外部工具,扩展 AI Agent 的能力。
示例:接入数据库查询工具
在 ~/.deveco/ai/config.json 中配置:
json
{
"mcp": {
"servers": [
{
"name": "sqlite-query",
"command": "npx",
"args": ["-y", "@anthropic/mcp-sqlite", "/path/to/database.db"],
"enabled": true
},
{
"name": "filesystem",
"command": "npx",
"args": ["-y", "@anthropic/mcp-filesystem", "/path/to/project"],
"enabled": true
}
]
}
}
12.4 自定义提示词模板
你可以在 ~/.deveco/ai/prompts/ 目录下创建自定义提示词模板:
markdown
<!-- ~/.deveco/ai/prompts/component_template.md -->
# HarmonyOS 组件开发规范
当你生成 ArkTS 组件时,请遵循以下规范:
1. 每个组件文件只包含一个 @Entry 或 @Component 结构
2. 状态变量声明在组件顶部,按用途分组并添加注释
3. 生命周期方法放在 build() 之前
4. 私有方法以 handle/on 开头命名
5. @Builder 方法放在 build() 之后
6. 每个 @Builder 方法都是一个独立的视觉模块
7. 所有可点击元素添加明确的 onClick 处理
8. 使用 $r() 引用资源文件
12.5 环境变量与 Shell 集成
在 ~/.zshrc 中添加 DevEco Code 相关配置:
bash
# --- DevEco Code 环境变量 ---
export DEVECO_MODEL="glm-5" # 默认模型
# export DEVECO_API_KEY="sk-xxx" # 自定义 API Key
export DEVECO_LOG_LEVEL="info" # 日志级别
# --- DevEco Code 别名 ---
alias dc='deveco' # 快速启动
alias dcu='deveco upgrade' # 快速升级
alias dcs='deveco status' # 快速查看状态
# --- 项目快速切换 ---
# 定义常用项目路径
export HARMONY_HOME=~/HarmonyOSProjects
alias hcd1='cd $HARMONY_HOME/EShopApp && deveco'
alias hcd2='cd $HARMONY_HOME/SocialApp && deveco'
alias hcd3='cd $HARMONY_HOME/ToolApp && deveco'
12.6 iTerm2 深度集成
为 DevEco Code 创建 iTerm2 专属 Profile:
- 打开 iTerm2 → Preferences → Profiles
- 点击 "+" 创建新 Profile,命名为 "DevEco Code"
- 设置配色方案(推荐 Solarized Dark 或 Dracula)
- 设置字体:推荐 JetBrains Mono 或 Fira Code(14pt)
- 在 "General" → "Command" 中设置 "Login Shell"
- 在 "Send text at start" 中输入
deveco(自动启动 DevEco Code)
配置热键窗口(Hotkey Window):
- iTerm2 → Preferences → Keys → Hotkey Window
- 勾选 "A hotkey opens a dedicated window"
- 设置热键为
⌥D(Option+D) - Profile 选择 "DevEco Code"
这样按 Option+D 就能从任何应用中快速呼出 DevEco Code 终端。
十三、更新与升级
13.1 deveco upgrade 命令
bash
# 在终端中直接升级
deveco upgrade
# 或在交互会话中
/upgrade
13.2 npm 重新安装升级
bash
npm install -g @deveco/deveco-code@latest
13.3 版本回退
bash
# 查看可用版本
npm view @deveco/deveco-code versions
# 安装指定版本
npm install -g @deveco/deveco-code@1.0.0
13.4 升级注意事项
- 配置文件不会被覆盖
- 对话历史会保留
- 登录状态通常不受影响
- 重大版本升级可能需要重新配置
十四、完整卸载流程
14.1 卸载运行时数据
bash
# 清理运行时数据
deveco uninstall
14.2 npm 全局卸载
bash
npm uninstall -g @deveco/deveco-code
# 如果是 OpenHarmony SIG 版本
npm uninstall -g @openharmony-sig/deveco-code
14.3 清理残留配置与缓存
bash
# 删除配置目录
rm -rf ~/.deveco
# 清理 npm 缓存
npm cache clean --force
# 检查是否还有残留
ls -la ~/ | grep deveco
14.4 卸载 Node.js(可选)
如果使用 Homebrew 安装:
bash
brew uninstall node@20
# 或
brew uninstall node
如果使用 fnm:
bash
fnm uninstall 20.18.1
# 卸载 fnm 本身
brew uninstall fnm
# 清理 ~/.zshrc 中的 fnm 配置
如果使用 nvm:
bash
nvm uninstall 20.18.1
# 卸载 nvm
rm -rf ~/.nvm
# 清理 ~/.zshrc 中的 nvm 配置
14.5 卸载 Homebrew(可选)
bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
14.6 卸载验证
bash
# 验证 DevEco Code 已卸载
deveco --version
# 期望:command not found
# 验证配置已删除
ls ~/.deveco
# 期望:No such file or directory
# 验证 Node.js 已卸载(如果卸载了的话)
node -v
# 期望:command not found
十五、常见问题与解决方案(FAQ)
15.1 安装类问题
Q1:brew install node 安装的是最新版而非 LTS
A:使用 brew install node@20 安装 LTS 版本,然后 brew link node@20 --force。
Q2:nvm 安装后命令找不到
A:检查 ~/.zshrc 中是否正确添加了 nvm 配置,执行 source ~/.zshrc 重新加载。
Q3:npm install -g 权限被拒绝
A:使用 fnm 或 nvm 管理 Node.js,或修改 npm 全局目录到用户目录。
15.2 登录类问题
Q4:浏览器没有自动打开
A:MacOS 上可以使用 open 命令手动打开链接:
bash
open "https://developer.huawei.com/consumer/cn/auth?..."
Q5:登录凭证过期
A:执行 deveco logout 后重新启动 DevEco Code 重新登录。
15.3 模型调用类问题
Q6:GLM-5.1 请求频率超限
A:等待 1 分钟重试,或切换到 DeepSeek 等第三方模型。
Q7:DeepSeek API 返回 401
A:检查 API Key 是否正确,确认密钥未过期。
15.4 MacOS 特有问题
Q8:Apple Silicon 上 node 运行在 Rosetta 模式
A:确保终端应用没有勾选"使用 Rosetta 打开"。在 Finder 中右键终端 → 显示简介 → 取消勾选"使用 Rosetta 打开"。
Q9:MacOS Gatekeeper 阻止执行
A:如果 npm 全局安装的脚本无法执行:
bash
# 移除隔离属性
xattr -cr $(npm config get prefix)/lib/node_modules/@deveco/deveco-code
Q10:终端中文显示乱码
A:确保终端使用 UTF-8 编码:
bash
# 在 ~/.zshrc 中添加
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
Q11:MacOS 升级后 git 命令不可用
A:MacOS 升级可能清除 CLT,重新安装:
bash
xcode-select --install
Q12:Homebrew 在 Apple Silicon 上报 "command not found"
A:将 Homebrew 添加到 PATH:
bash
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
source ~/.zprofile
15.5 性能与稳定性问题
Q13:DevEco Code 长时间使用后变慢
A:使用 /compact 压缩上下文,或 /clear 清空历史重新开始。
Q14:终端显示不完整或错位
A:调整终端窗口大小,确保使用等宽字体,推荐使用 iTerm2 + JetBrains Mono。
十六、总结
DevEco Code 的发布标志着 HarmonyOS 开发工具链迈入了 Agentic Coding 时代。作为华为面向鸿蒙生态推出的终端 AI Agent 工具,它凭借对 ArkTS 语法体系的深度理解和终端原生的高效交互形态,成为 MacOS 平台上鸿蒙开发者的"新神器"。
本文从 MacOS 平台的独特视角出发,完整覆盖了以下核心内容:
- 环境搭建:Xcode CLT → Homebrew → Node.js(fnm/nvm 推荐),解决了 Apple Silicon 架构兼容性问题
- 安装部署:npm 全局安装,详细的权限问题排查
- 模型配置:GLM-5.1 免费使用 + DeepSeek/通义千问/智谱/Ollama 全接入
- 核心功能:代码生成、UI 构建、卡片开发、Bug 修复,附完整代码示例
- 命令体系:斜杠命令 + MacOS 快捷键
- 实战案例:六个贴近真实场景的完整代码案例
- 协同工作:与 DevEco Studio 的高效配合
- 高级配置:iTerm2 集成、MCP 扩展、记忆文件
- 维护管理:升级与完整卸载
核心建议:
- 使用 fnm 管理 Node.js,避免权限问题,切换版本方便
- 使用 iTerm2 作为终端,配合热键窗口随时呼出 DevEco Code
- 为每个项目创建
.deveco-rules.md,让 AI 更"懂"你的项目 - 善用
/compact管理上下文,保持长对话的高效性 - 关注版本更新,华为正在快速迭代新功能
附录
附录 A:DevEco Code 完整命令参考表
CLI 命令:
| 命令 | 功能 | 示例 |
|---|---|---|
deveco |
启动交互会话 | deveco |
deveco --version |
查看版本 | deveco -v |
deveco --help |
帮助信息 | deveco -h |
deveco upgrade |
升级 | deveco upgrade |
deveco uninstall |
卸载运行时数据 | deveco uninstall |
deveco logout |
退出登录 | deveco logout |
deveco status |
查看状态 | deveco status |
deveco --cwd <path> |
指定目录启动 | deveco --cwd ~/MyApp |
斜杠命令:
| 命令 | 功能 | 频率 |
|---|---|---|
/help |
帮助 | ⭐⭐⭐⭐⭐ |
/model |
切换模型 | ⭐⭐⭐⭐⭐ |
/clear |
清空对话 | ⭐⭐⭐⭐⭐ |
/compact |
压缩上下文 | ⭐⭐⭐⭐ |
/exit |
退出 | ⭐⭐⭐⭐ |
/cost |
Token 统计 | ⭐⭐⭐ |
/diff |
查看变更 | ⭐⭐⭐ |
/undo |
撤销修改 | ⭐⭐⭐ |
/status |
查看状态 | ⭐⭐⭐ |
/config |
配置管理 | ⭐⭐ |
/add-dir |
添加目录 | ⭐⭐ |
/init |
初始化项目 | ⭐⭐ |
switch_cwd |
切换项目 | ⭐⭐⭐ |
/doctor |
健康检查 | ⭐ |
/bug |
报告 Bug | ⭐ |
附录 B:MacOS 环境变量与配置文件速查表
关键文件路径:
| 文件 | 路径 | 说明 |
|---|---|---|
| 模型配置 | ~/.deveco/ai/config.json |
模型供应商和参数 |
| 登录凭证 | ~/.deveco/auth/credentials.json |
加密认证信息 |
| 运行日志 | ~/.deveco/logs/deveco-code.log |
排障日志 |
| 全局记忆 | ~/.deveco/ai/memory.md |
全局 AI 偏好 |
| 项目记忆 | {项目根目录}/.deveco-rules.md |
项目规范 |
| Shell 配置 | ~/.zshrc |
zsh 配置 |
| Homebrew (AS) | /opt/homebrew/ |
Apple Silicon 路径 |
| Homebrew (Intel) | /usr/local/ |
Intel Mac 路径 |
附录 C:MacOS 终端命令速查
bash
# === 系统信息 ===
uname -m # 查看 CPU 架构(arm64/x86_64)
sw_vers # 查看 MacOS 版本
sysctl -n machdep.cpu.brand_string # CPU 型号
system_profiler SPHardwareDataType # 硬件概览
# === Homebrew ===
brew update # 更新 Homebrew
brew upgrade # 升级所有包
brew list # 已安装的包
brew doctor # 健康检查
brew cleanup # 清理缓存
# === Node.js ===
node -v # Node.js 版本
npm -v # npm 版本
npm list -g --depth=0 # 全局包列表
npm config get prefix # 全局安装路径
npm config get registry # 当前镜像源
# === 文件操作 ===
ls -la # 详细列表
open . # 在 Finder 中打开
open -a "DevEco Studio" # 打开应用
pbcopy < file.txt # 复制文件内容到剪贴板
pbpaste > file.txt # 粘贴剪贴板到文件
# === 网络 ===
ping api.deepseek.com # 测试连通性
curl -I https://api.deepseek.com # HTTP 头信息
lsof -i :7890 # 查看端口占用
# === Git ===
git status # 仓库状态
git log --oneline -10 # 最近10次提交
git diff # 查看变更
# === hdc ===
hdc list targets # 列出设备
hdc shell aa start -a EntryAbility -b com.example.app # 启动应用
hdc shell hilog # 查看日志
附录D:模型 API 参数对照表
| 模型 | Provider | API Base URL | Model ID | 费用 |
|---|---|---|---|---|
| GLM-5.1 | DevEco(内置) | 内置 | glm-5 / glm-5.1 |
免费 |
| DeepSeek Chat | DeepSeek | https://api.deepseek.com |
deepseek-chat |
按量计费 |
| DeepSeek Coder | DeepSeek | https://api.deepseek.com |
deepseek-coder |
按量计费 |
| 通义千问 Max | 阿里云 | https://dashscope.aliyuncs.com/compatible-mode/v1 |
qwen-max |
按量计费 |
| 智谱 GLM-4 | 智谱 AI | https://open.bigmodel.cn/api/paas/v4 |
glm-4-plus |
按量计费 |
| Moonshot v1 | 月之暗面 | https://api.moonshot.cn/v1 |
moonshot-v1-128k |
按量计费 |
| Ollama 本地 | Ollama | http://localhost:11434/v1 |
自定义 | 免费 |
学习资料与推荐资源
官方资源
-
华为开发者联盟官网
- 地址:https://developer.huawei.com/consumer/cn/
- 内容:DevEco Studio 下载、官方文档、开发者论坛
-
HarmonyOS 官方文档
- 地址:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides
- 内容:ArkTS 语法指南、API 参考、开发指南
-
DevEco Code 官方介绍
- 地址:华为开发者论坛 DevEco Code 专区
- 内容:最新功能介绍、更新日志、使用教程
-
华为开发者学堂
- 地址:https://developer.huawei.com/consumer/cn/training/
- 内容:免费的鸿蒙开发在线课程
社区资源
-
51CTO 鸿蒙开发者社区
- 地址:https://ost.51cto.com/
- 内容:大量 DevEco Code 实战文章和教程
-
InfoQ 鸿蒙开发专栏
- 地址:https://xie.infoq.cn/
- 内容:深度的技术分析和最佳实践
-
OpenCode 开源项目
- 地址:GitHub 搜索 "OpenCode"
- 内容:DevEco Code 的底层开源框架源码
-
鸿蒙开发者交流群
- 华为开发者论坛中可找到各类技术交流群
推荐书籍与课程
- 《鸿蒙应用开发实战》 --- 系统学习 HarmonyOS 应用开发
- 《ArkTS 编程语言详解》 --- 深入理解 ArkTS 语法体系
- 华为官方 Codelabs --- 动手实践教程,边学边做
工具推荐
-
nvm(Node Version Manager) --- Node.js 版本管理工具
-
Git for Mac --- 版本控制工具
-
DeepSeek 开放平台 --- 获取 DeepSeek API Key
持续学习建议
- 第一阶段(1-2 周):熟悉 DevEco Code 的基本操作,使用内置模型完成简单的代码生成
- 第二阶段(2-4 周):接入 DeepSeek 等模型,尝试完整的实战案例
- 第三阶段(1-2 月):深度定制 Agent 行为,建立项目级开发规范
- 第四阶段(持续):关注 DevEco Code 版本更新,探索 MCP 等高级功能
免责声明:本文基于 DevEco Code 发布初期(HDC 2026 后)的公开信息编写。由于 DevEco Code 处于快速迭代中,部分命令、配置项和功能可能在后续版本中发生变化,请以华为官方最新文档为准。文中涉及的第三方服务(如 DeepSeek API)的费用和政策以各服务商官方说明为准。
版本信息:本文写于 2026 年 7 月,基于 DevEco Code v1.x 版本。