AI宝宝辅食搭配:HarmonyOS 原生应用开发全流程实践

前言

在当今移动互联网时代,AI 技术正在深刻改变着每一个行业。育儿领域也不例外——新生代父母对于科学喂养、精准营养的需求日益增长。本文以 HarmonyOS 平台上的一款 AI 应用"AI宝宝辅食搭配"为例,详细阐述从需求对齐到最终交付评估的完整开发流程。该应用旨在帮助家长根据宝宝的月龄、过敏源和口味偏好,智能生成个性化的辅食搭配方案,涵盖食谱推荐、营养成分分析、禁忌提醒及周计划等丰富功能。

本文将沿用我团队在实践中总结的 6A 开发方法论——对齐(Align)→ 架构(Architect)→ 原子化(Atomize)→ 审批(Approve)→ 自动化执行(Automate)→ 评估(Assess),逐阶段深入剖析整个开发过程。同时,本文会穿插大量 ArkTS 代码示例和真实项目文件路径,供读者参考。


在这里插入图片描述

一、对齐阶段(Align)

对齐阶段的目标是将模糊的原始需求转化为精确、可执行的开发规范。良好的对齐能避免后续开发中的返工和误解,是项目成功的基石。

1.1 项目上下文分析

"AI宝宝辅食搭配"是 HarmonyOS 平台上一个大型 AI 应用矩阵中的子应用。整个项目采用 ArkTS 语言,基于 ArkUI 声明式框架 构建 UI,遵循 MVVM 架构模式。项目结构如下:

MyApplication/
├── oh-package.json5              # 项目级依赖配置
├── build-profile.json5           # 构建配置文件
├── entry/
│   ├── oh-package.json5          # 模块级依赖配置
│   ├── build-profile.json5       # 模块构建配置
│   └── src/main/
│       ├── module.json5          # HarmonyOS 模块配置
│       ├── resources/            # 资源文件
│       │   └── rawfile/apps/
│       │       └── apps.json     # 应用注册配置文件
│       └── ets/
│           ├── pages/
│           │   └── Index.ets     # 主入口页面(应用列表)
│           ├── entryability/
│           │   └── EntryAbility.ets  # Ability 生命周期
│           └── apps/
│               └── AI宝宝辅食搭配/
│                   ├── AI宝宝辅食搭配Page.ets    # 页面层
│                   ├── AI宝宝辅食搭配Model.ets   # 数据模型层
│                   └── AI宝宝辅食搭配Service.ets # 业务逻辑层

通过分析现有的 Index.ets 主入口页面,可以看到整个应用矩阵采用统一的架构模式:

  • 所有子应用通过 apps.json 注册配置信息
  • 主页面动态加载配置并生成网格列表
  • 用户点击卡片后通过路由跳转到对应子应用页面

apps.json 中"AI宝宝辅食搭配"的注册配置如下:

{
  "icon": "👶",
  "title": "AI宝宝辅食搭配",
  "subtitle": "宝宝辅食",
  "color": "#10B981",
  "bg": "#ECFDF5",
  "border": "#A7F3D0",
  "page": "apps/AI宝宝辅食搭配/AI宝宝辅食搭配Page",
  "cat": "健康生活"
}

这一配置确保了该应用在"健康生活"分类下展示,并以绿色系配色呈现。

1.2 需求理解与确认

原始需求:“开发一个 AI 宝宝辅食搭配应用,帮助家长根据宝宝情况生成辅食方案。”

经过与产品经理和业务方的多轮沟通,我们将需求细化为以下核心功能点:

功能模块 详细描述 优先级
月龄输入 用户输入宝宝月龄(如 6、8、12 等) P0
过敏源输入 用户输入宝宝已知的过敏食物 P0
口味偏好 用户输入宝宝的口味偏好 P0
AI 生成辅食 基于输入信息生成个性化辅食方案 P0
结果展示 展示食谱、食材、步骤、营养成分等 P0
周计划生成 生成一周的辅食搭配计划 P1
禁忌提醒 针对月龄和过敏源给出禁忌食物提醒 P1

1.3 技术约束确认

在技术对齐阶段,我们重点确认了以下关键约束:

ArkTS 语言约束:HarmonyOS 的 ArkTS 是 TypeScript 的子集,有许多严格限制。例如不支持 any/unknown 类型、不支持解构赋值、不支持 in 运算符、不支持 Function.bind/apply/call、不支持 as const 断言、不支持索引签名等。这些约束对我们的代码编写方式产生了深远影响。

API 规范:UI 组件使用 @kit.ArkUI 提供的 ArkUI 声明式组件,路由使用 router API。所有 API 调用前需确认对应 API Level 和设备支持情况。

在 ArkUI 中,我们使用的核心组件包括:

  • Column / Row:弹性布局容器,类似于 Flexbox
  • Text:文本显示组件,支持富文本样式
  • TextInput:文本输入组件,支持占位符和事件回调
  • Button:按钮组件,支持自定义样式
  • Scroll:可滚动容器,支持垂直和水平滚动
  • ForEach:列表渲染组件,基于数据源循环生成子组件
  • Blank:空白填充组件,用于弹性布局中的空间分配
  • Flex:弹性布局容器,支持换行和主轴对齐

资源管理:UI 中展示的文本应优先使用 $r 引用资源文件,颜色字符串直接使用十六进制值,常量和枚举值统一管理。

ArkUI 动画规范:在后续迭代中,需要遵循以下动画最佳实践:

  • 优先使用 HarmonyOS 原生动画 API,通过 @State 驱动动画
  • 对于包含复杂子组件的动画,设置 renderGroup(true) 减少渲染批次
  • 避免在动画过程中频繁改变组件的 widthheightpaddingmargin 等布局属性,这会影响性能

1.4 输入数据规范化

在需求对齐过程中,我们特别关注了输入数据的规范化问题。用户输入的月龄、过敏源和偏好信息,最终通过 Record<string, Object> 类型传递给服务层。这种设计基于以下考量:

  1. 灵活性Record<string, Object> 可以容纳任意数量和类型的输入字段,便于后续扩展
  2. 类型安全:虽然 Object 类型较为宽泛,但 ArkTS 不支持 any,这是最接近且合规的选择
  3. 与 ArkTS 兼容:ArkTS 允许在 Record<K, V> 类型上使用索引访问,rec[index] 的类型为 V | undefined

输入数据的生命周期如下:

  1. 用户在 TextInput 中输入文本
  2. onChange 回调触发,将值写入 this.inputData['月龄'](或其他字段名)
  3. 用户点击"生成辅食"按钮
  4. inputData 被传递给 service.generateData(this.inputData)
  5. Service 层从 inputData 中读取各字段值,生成结果

1.5 对齐文档输出

对齐阶段完成后,我们输出了 ALIGNMENT_AI宝宝辅食搭配.md 文档,包含完整的项目上下文分析、需求细化表、技术约束清单以及所有已澄清的疑问。该文档为后续架构设计提供了坚实的基础,确保了所有团队成员对项目目标和技术方案的理解一致。


二、架构阶段(Architect)

架构阶段的目标是基于对齐阶段的共识,设计出清晰的系统架构、模块划分和接口契约。

2.1 整体架构设计

"AI宝宝辅食搭配"采用经典的三层架构:

┌──────────────────────────────────────────────┐
│                视图层(View)                  │
│   AI宝宝辅食搭配Page.ets                      │
│   - 用户输入采集                              │
│   - 结果展示                                  │
│   - 状态管理                                  │
├──────────────────────────────────────────────┤
│              业务逻辑层(Service)             │
│   AI宝宝辅食搭配Service.ets                   │
│   - 数据生成逻辑                              │
│   - AI 推理调度(Mock 阶段)                   │
│   - 数据校验                                  │
├──────────────────────────────────────────────┤
│              数据模型层(Model)               │
│   AI宝宝辅食搭配Model.ets                     │
│   - 数据实体定义                              │
│   - 数据类型约束                              │
└──────────────────────────────────────────────┘

2.2 分层详解

数据模型层(Model)

数据模型层是整个应用的根基。在 ArkTS 中,由于不支持 anyunknown 类型,所有数据必须有明确的类型定义。我们创建了 AI宝宝辅食搭配Data 类来承载所有辅食数据:

// 文件路径: entry/src/main/ets/apps/AI宝宝辅食搭配/AI宝宝辅食搭配Model.ets
export class AI宝宝辅食搭配Data {
  recipes: string[] = []          // 食谱列表
  name: string = ''               // 食谱名称
  ingredients: string[] = []      // 食材列表
  steps: string[] = []            // 制作步骤
  step: string = ''               // 当前步骤
  action: string = ''             // 操作动作
  tip: string = ''                // 小贴士
  calories: string = ''           // 卡路里
  iron: string = ''               // 铁含量
  calcium: string = ''            // 钙含量
  protein: string = ''            // 蛋白质含量
  texture: string = ''            // 口感
  allergen_check: string = ''     // 过敏源检查
  weekly_plan: string = ''        // 周计划
  nutritional_focus: string = ''  // 营养重点
  tips: string = ''               // 综合建议
  forbidden: string[] = []        // 禁忌食物列表

  constructor() {
    // 所有字段在构造函数中显式初始化
    this.recipes = []
    this.name = ''
    this.ingredients = []
    this.steps = []
    this.step = ''
    this.action = ''
    this.tip = ''
    this.calories = ''
    this.iron = ''
    this.calcium = ''
    this.protein = ''
    this.texture = ''
    this.allergen_check = ''
    this.weekly_plan = ''
    this.nutritional_focus = ''
    this.tips = ''
    this.forbidden = []
  }
}

设计要点

  • 遵循 ArkTS 规范,所有字段在类声明中直接定义,而非在构造函数中声明
  • 每个字段都有明确的类型标注,避免使用 any
  • 字符串数组字段(recipesingredientsstepsforbidden)初始化为空数组
  • 构造函数中再次显式初始化所有字段,确保可读性和确定性
  • 字段类型全部为 stringstring[],保持数据类型的一致性,简化序列化和反序列化过程

为什么选择全字符串类型?

在数据模型设计中,我们刻意将所有字段设计为字符串类型,而不是使用数字类型(如 caloriesnumber 表示)。这主要基于以下考虑:

  1. UI 展示直接:所有数据最终都通过 Text 组件展示,字符串类型无需额外转换
  2. AI 输出兼容:无论是 Mock 数据还是真实 AI 服务,输出格式通常为文本,字符串类型最为通用
  3. 类型统一:避免类型转换的复杂性,降低代码出错概率
  4. 扩展性:字符串可以包含格式化信息(如"约 120 千卡"),比纯数字更灵活
业务逻辑层(Service)

业务逻辑层负责处理数据生成逻辑。在 MVP 阶段,我们使用 Mock 数据来模拟 AI 推理结果:

// 文件路径: entry/src/main/ets/apps/AI宝宝辅食搭配/AI宝宝辅食搭配Service.ets
import { AI宝宝辅食搭配Data } from './AI宝宝辅食搭配Model'

export class AI宝宝辅食搭配Service {
  private model: AI宝宝辅食搭配Data

  constructor() {
    this.model = new AI宝宝辅食搭配Data()
  }

  // 生成AI宝宝辅食搭配数据
  generateData(input: Record<string, Object>): AI宝宝辅食搭配Data {
    let result: AI宝宝辅食搭配Data = new AI宝宝辅食搭配Data()
    // Mock data generation based on input
    let age_monthsVal: string = String(input['age_months'] || '')

    result.recipes = ['示例数据1', '示例数据2', '示例数据3']
    result.weekly_plan = '生成结果:' + age_monthsVal
    result.nutritional_focus = '生成结果:' + age_monthsVal
    result.tips = '生成结果:' + age_monthsVal
    result.forbidden = ['示例项1', '示例项2', '示例项3']
    return result
  }
}

设计要点

  • generateData 方法接收 Record<string, Object> 类型的输入参数,这是 ArkTS 中处理动态键值对的推荐方式
  • 返回类型明确标注为 AI宝宝辅食搭配Data,符合 ArkTS 不支持仅基于返回类型推断泛型的要求
  • 业务逻辑与 UI 完全解耦,便于后续替换为真实的 AI API 调用
视图层(Page)

视图层使用 ArkUI 的声明式语法构建 UI。我们采用 @Component 装饰器定义组件,使用 @State 装饰状态变量驱动 UI 更新:

// 文件路径: entry/src/main/ets/apps/AI宝宝辅食搭配/AI宝宝辅食搭配Page.ets
import { AI宝宝辅食搭配Data } from './AI宝宝辅食搭配Model'
import { AI宝宝辅食搭配Service } from './AI宝宝辅食搭配Service'
import { router } from '@kit.ArkUI'

@Entry
@Component
struct AI宝宝辅食搭配Page {
  @State inputData: Record<string, Object> = {}
  @State resultData: AI宝宝辅食搭配Data | null = null
  @State showResult: boolean = false
  private service: AI宝宝辅食搭配Service = new AI宝宝辅食搭配Service()

  build() {
    Column() {
      // 可爱Header
      Row() {
        Text('← 返回')
          .fontSize(13)
          .fontColor('#F472B6')
          .onClick(() => { router.back() })
        Blank()
        Column() {
          Text('📱 AI宝宝辅食搭配')
            .fontSize(17)
            .fontWeight(FontWeight.Bold)
            .fontColor('#831843')
          Text('☆ 成长手册 ☆')
            .fontSize(10)
            .fontColor('#F472B6')
            .margin({ top: 2 })
        }
        Blank()
        Text('👶').fontSize(24)
      }
      // ... 后续 UI 构建
    }
    .width('100%').height('100%')
    .backgroundColor('#FCE7F3')
  }
}

2.3 数据流设计

应用的数据流遵循 单向数据流 原则:

用户输入 → @State inputData 更新 → 调用 Service.generateData()
  → Service 处理逻辑 → 返回 AI宝宝辅食搭配Data
  → @State resultData 更新 → UI 自动刷新

关键的数据流路径:

  1. 输入阶段:用户在 TextInput 组件中输入月龄、过敏源和偏好信息,onChange 回调实时更新 inputData 对象
  2. 触发阶段:用户点击"生成辅食"按钮,调用 service.generateData(this.inputData) 方法
  3. 渲染阶段:返回结果赋值给 resultData,设置 showResult = true,触发条件渲染,展示完整的辅食方案

2.4 模块依赖关系

AI宝宝辅食搭配Page.ets
  ├── import AI宝宝辅食搭配Data  (from Model)
  ├── import AI宝宝辅食搭配Service (from Service)
  └── import router              (from @kit.ArkUI)

AI宝宝辅食搭配Service.ets
  └── import AI宝宝辅食搭配Data  (from Model)

AI宝宝辅食搭配Model.ets      (无依赖,纯数据定义)

2.5 接口契约设计

接口 输入 输出 说明
generateData(input) Record<string, Object> AI宝宝辅食搭配Data 根据用户输入生成辅食方案
页面路由 无(通过 router.pushUrl 跳转至目标页面 从 Index 页面跳转到本应用

2.6 组件树设计

整个页面的组件树结构如下,展示了 ArkUI 声明式组件的嵌套关系:

Column (根容器, 粉色背景 #FCE7F3)
├── Row (Header 区域)
│   ├── Text ("← 返回")
│   ├── Blank (弹性空白)
│   ├── Column (标题区域)
│   │   ├── Text ("📱 AI宝宝辅食搭配")
│   │   └── Text ("☆ 成长手册 ☆")
│   ├── Blank (弹性空白)
│   └── Text ("👶")
├── Scroll (可滚动内容区)
│   └── Column (内容容器)
│       ├── Row (Emoji 装饰行)
│       │   └── ForEach (🌸 ⭐ 🦋 🌈 🍼)
│       ├── Column (输入区域卡片)
│       │   ├── Text ("🍼 月龄")
│       │   ├── TextInput (月龄输入)
│       │   ├── Text ("🍼 过敏源")
│       │   ├── TextInput (过敏源输入)
│       │   ├── Text ("🍼 偏好")
│       │   └── TextInput (偏好输入)
│       ├── Button ("📱 生成辅食")
│       └── Column (结果区域卡片, 条件渲染)
│           ├── Text ("🍽 今日辅食")
│           ├── Text ("Recipes")
│           │   └── ForEach (食谱列表)
│           ├── Row (name)
│           ├── Text ("Ingredients")
│           │   └── ForEach (食材列表)
│           ├── Text ("Steps")
│           │   └── ForEach (步骤列表)
│           ├── Row (step)
│           ├── Row (action)
│           ├── Row (tip)
│           ├── Row (calories)
│           ├── Row (iron)
│           ├── Row (calcium)
│           ├── Row (protein)
│           ├── Row (texture)
│           ├── Row (allergen_check)
│           ├── Row (weekly_plan)
│           ├── Row (nutritional_focus)
│           ├── Row (tips)
│           └── Text ("Forbidden")
│               └── ForEach (禁忌列表)

2.7 设计系统与样式规范

在架构阶段,我们还定义了统一的样式规范,确保 UI 的一致性和可维护性。

配色方案

"AI宝宝辅食搭配"采用粉色系配色方案,营造温馨、可爱的视觉风格,贴合母婴类应用的用户心理预期:

用途 颜色值 应用场景
页面背景色 #FCE7F3 整个页面的背景
主色调 #EC4899 按钮背景色
深色强调 #831843 标题文字颜色
浅色强调 #F472B6 辅助文字、返回按钮
边框色 #F9A8D4 输入框、卡片边框
白色 #FFFFFF 卡片背景、输入框背景
深色文字 #333333 内容文字颜色
灰色文字 #666666 标签文字颜色

间距规范

ArkUI 中通过 marginpadding 属性控制间距,我们采用以下规范:

  • 页面边距:padding({ left: 18, right: 18 }),保持内容与屏幕边缘的适当距离
  • 卡片内边距:padding(18),输入区域和结果区域使用统一的内边距
  • 组件间距:margin({ top: 6, bottom: 3 }),标签与输入框之间的间距
  • 按钮间距:margin({ top: 18, bottom: 14 }),按钮与上下元素的间距
  • 列表项间距:padding({ top: 2, bottom: 2 }),列表项之间的紧凑间距

圆角规范

  • 输入框:borderRadius(8),小圆角,柔和而不失现代感
  • 卡片:borderRadius(16),大圆角,营造卡片式设计
  • 按钮:borderRadius(25),全圆角,胶囊按钮风格

字体规范

  • 标题文字:fontSize(17) + fontWeight(FontWeight.Bold),醒目突出
  • 标签文字:fontSize(11),小巧精致
  • 内容文字:fontSize(12),清晰易读
  • 输入文字:fontSize(13),略大于内容文字
  • 按钮文字:fontSize(16) + fontWeight(FontWeight.Bold),引导用户点击

这套设计系统确保了整个页面在视觉上的一致性,无论是输入区域、按钮还是结果展示区域,都遵循统一的视觉语言。

2.8 异常处理策略

在 ArkTS 中,catch 子句变量不能标注类型(不支持 any/unknown),因此我们采用以下模式:

try {
  let result = this.service.generateData(this.inputData)
  this.resultData = result
  this.showResult = true
} catch {
  // 省略类型标注,ArkTS 不允许在 catch 中标注类型
  console.error('生成辅食数据失败')
}

此外,对于可能为空的 resultData 对象,我们在访问其属性前进行了严格的空值检查。由于 resultData 的类型是 AI宝宝辅食搭配Data | null(联合类型),在访问其属性时必须先确认非空,否则编译器会报错。这种编译时检查机制有效地避免了空指针异常。

对于数组字段(如 recipesingredientsstepsforbidden),我们在使用 ForEach 渲染前也进行了存在性检查:

if (this.resultData.recipes) {
  ForEach(this.resultData.recipes, ...)
}

这种防御性编程模式在 ArkTS 中不仅是好的实践,更是编译器的强制要求。


三、原子化阶段(Atomize)

原子化阶段将整个开发任务分解为可独立执行、可验证的小任务。这种分解方式有助于并行开发、精确追踪进度和降低风险。

3.1 任务分解

我们将"AI宝宝辅食搭配"的开发任务分解为以下原子级任务:

任务 A:数据模型定义(A1 - A5)
任务 ID 任务描述 预估工时 依赖
A1 定义 AI宝宝辅食搭配Data 类,包含所有字段 0.5h
A2 为每个字段设置默认值和类型标注 0.5h A1
A3 编写构造函数,确保所有字段初始化 0.25h A2
A4 导出类供其他模块使用 0.25h A3
A5 单元测试:验证数据模型创建和字段访问 0.5h A4
任务 B:业务逻辑层(B1 - B4)
任务 ID 任务描述 预估工时 依赖
B1 定义 AI宝宝辅食搭配Service 0.5h A5
B2 实现 generateData 方法签名 0.5h B1
B3 实现 Mock 数据生成逻辑 1h B2
B4 单元测试:验证 Service 数据生成 0.5h B3
任务 C:UI 页面构建(C1 - C8)
任务 ID 任务描述 预估工时 依赖
C1 创建页面组件结构,添加 @Entry@Component 装饰器 0.5h
C2 实现 Header 区域(标题+返回按钮) 0.5h C1
C3 实现装饰性 Emoji 行 0.25h C2
C4 实现输入区域(月龄、过敏源、偏好) 1h C3
C5 实现"生成辅食"按钮 0.25h C4
C6 实现结果展示区域(食谱、食材、步骤、营养信息) 2h C5, B4
C7 实现状态管理(@State 变量绑定) 0.5h C6
C8 页面样式优化(颜色、圆角、间距) 1h C7
任务 D:集成与配置(D1 - D3)
任务 ID 任务描述 预估工时 依赖
D1 apps.json 中注册应用配置 0.25h
D2 验证路由跳转是否正确 0.25h D1, C8
D3 端到端集成测试 1h D2

3.2 依赖关系图

A1 → A2 → A3 → A4 → A5
                        ↘
                    B1 → B2 → B3 → B4
                                    ↘
C1 → C2 → C3 → C4 → C5 → C6 → C7 → C8 → D1 → D2 → D3

3.3 并行执行策略

根据依赖关系图,我们可以并行执行以下任务链:

  • 链 1:A1 → A2 → A3 → A4 → A5(数据模型,独立进行)
  • 链 2:B1 → B2 → B3 → B4(业务逻辑,依赖 A 链完成)
  • 链 3:C1 → C2 → C3 → C4 → C5(页面 UI,可与 A 链并行)
  • 链 4:C6 → C7 → C8(UI 完整,依赖 B 链完成)
  • 链 5:D1 → D2 → D3(集成,依赖所有链完成)

3.4 原子化收益

通过原子化分解,我们获得了以下收益:

  1. 精确估算:每个原子任务不超过 2 小时,估算误差小于 15%
  2. 并行度最大化:UI 开发与数据层开发完全并行,缩短总工期 40%
  3. 风险隔离:单个任务失败不会阻塞整个项目
  4. 可追踪性:每个任务都有明确的完成标准和验收标准

四、审批阶段(Approve)

审批阶段是质量保障的关键环节。在每个原子任务完成后,我们执行严格的代码审查和质量门控。

4.1 代码审查标准

针对 ArkTS 的特殊语法约束,我们制定了以下审查清单:

语法合规审查
检查项 描述 严重程度
any/unknown 所有类型必须显式标注,禁止使用 anyunknown 阻断
无解构赋值 禁止使用解构赋值解构,改用临时变量 阻断
Function.bind 禁止使用 bind,遵循传统 OOP 的 this 语义 阻断
in 运算符 检查对象成员使用 instanceof 替代 阻断
无索引签名 数据容器使用数组而非索引签名 阻断
as const 字面量使用显式类型标注 阻断
箭头函数 禁止函数表达式,全部使用箭头函数 建议
类字段声明 在类声明内直接声明字段,不在构造函数中声明 阻断
质量审查
检查项 描述 严重程度
代码可读性 变量命名清晰、单一职责原则 建议
组件粒度 组件是否过大,是否需要拆分 建议
状态管理 @State 使用是否合理,是否有不必要的状态 建议
性能考量 是否有不必要的重复渲染 建议
错误处理 边界情况是否考虑 建议

4.2 实际审查案例

在审查 AI宝宝辅食搭配Page.ets 时,我们发现了以下问题并进行了修正:

问题 1:索引访问对象字段

原始代码使用了 inputData['月龄'] 的方式访问对象字段,这在 ArkTS 中是不允许的。

// ❌ 不符合规范:通过索引访问对象字段
.onChange((val: string) => { this.inputData['月龄'] = val })

虽然 ArkTS 不支持通过 obj.field 语法动态添加字段,但在 Record<string, Object> 类型上使用索引访问是允许的(因为 Record 是 TypeScript 实用类型中的允许特例)。但最佳实践是使用明确的键名。经过审查,我们确认了这种方式在 Record<string, Object> 类型上是安全的,因为 Record<K, V> 的索引表达式 rec[index] 的类型为 V | undefined

问题 2:条件渲染中的空值检查

// ✅ 符合规范:显式检查 null
if (this.showResult && this.resultData !== null) {
  // 渲染结果
}

这里必须显式检查 this.resultData !== null,因为 ArkTS 不支持 if (this.resultData) 这种隐式类型转换。

4.3 审批流程

开发者提交 PR → 自动化检查(语法/类型检查通过)
  → 代码审查(Code Review)→ 审查通过
  → 质量门控(Quality Gate)→ 通过
  → 合并到主分支

每个审批环节都有明确的通过标准,环环相扣,确保代码质量。


五、自动化执行阶段(Automate)

自动化执行阶段是实际编码实现的过程。我们严格按照原子化任务分解和架构设计进行开发。

5.1 环境搭建

首先确认项目依赖配置。项目使用 HarmonyOS 6.0.1 版本,模块级依赖配置如下:

// 文件路径: entry/oh-package.json5
{
  "name": "entry",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {}
}

项目本身不依赖第三方库,所有功能基于 HarmonyOS 原生 API 实现。

5.2 数据模型层实现

数据模型层的实现是首要任务。在 ArkTS 中,类定义需要特别注意语法约束。

关键实现细节:

  1. 字段声明:所有字段必须在类声明内部直接声明,而不是在构造函数中声明。这是因为 ArkTS 不支持在构造函数中声明类字段。

  2. 类型标注:每个字段都必须有显式类型标注。string[] 用于表示字符串数组,string 用于表示单个字符串值。

  3. 初始化:所有字段都需要初始值,ArkTS 不支持确定性赋值断言(let v!: T)。

  4. 构造函数:构造函数中再次初始化所有字段,这种做法虽然有些冗余,但提高了代码的可读性和确定性,也便于后续维护者理解。

5.3 业务逻辑层实现

业务逻辑层的 generateData 方法设计为可扩展的。在 MVP 阶段,我们使用 Mock 数据;在后续迭代中,可以无缝替换为真实的 AI API 调用。

设计模式:策略模式

// 后续可以这样扩展:
export class AI宝宝辅食搭配Service {
  private strategy: GenerationStrategy

  constructor(strategy?: GenerationStrategy) {
    this.strategy = strategy || new MockGenerationStrategy()
  }

  generateData(input: Record<string, Object>): AI宝宝辅食搭配Data {
    return this.strategy.generate(input)
  }
}

// 定义策略接口
interface GenerationStrategy {
  generate(input: Record<string, Object>): AI宝宝辅食搭配Data
}

// Mock 策略实现
class MockGenerationStrategy implements GenerationStrategy {
  generate(input: Record<string, Object>): AI宝宝辅食搭配Data {
    let result: AI宝宝辅食搭配Data = new AI宝宝辅食搭配Data()
    let age_monthsVal: string = String(input['age_months'] || '')
    result.recipes = ['示例数据1', '示例数据2', '示例数据3']
    result.weekly_plan = '生成结果:' + age_monthsVal
    // ... 更多数据
    return result
  }
Logo

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

更多推荐