从0到1:HarmonyOS AI公众号选题应用的六阶段开发实践
从0到1:HarmonyOS AI公众号选题应用的六阶段开发实践
摘要:本文以 HarmonyOS 平台上的 AI 公众号选题应用为实战案例,详细阐述了一套六阶段开发方法论——对齐(Align)、架构(Architect)、原子化(Atomize)、审批(Approve)、自动化执行(Automate)、评估(Assess)。文章从项目上下文分析出发,贯穿 ArkTS 语法约束、ArkUI 声明式 UI 开发、数据模型设计、服务层封装等核心环节,提供了完整的代码示例和技术决策记录。全文约 10000 字,适合 HarmonyOS 应用开发者、AI 产品经理以及关注结构化开发流程的技术团队阅读。

一、对齐阶段(Align)
对齐阶段的目标是将模糊需求转化为精确规范。任何开发项目在启动前,都必须完成项目上下文分析和需求理解确认,这是后续所有工作的基石。
1.1 项目上下文分析
1.1.1 现有项目结构
我们的项目是一个 HarmonyOS 应用,使用 ArkTS 语言开发,项目根目录为 MyApplication。通过分析项目目录结构,我们可以看到以下关键路径:
entry/src/main/ets/
├── pages/
│ └── Index.ets # 主入口页面,应用列表
├── apps/
│ ├── AI公众号选题/
│ │ ├── AI公众号选题Page.ets # 选题页面
│ │ ├── AI公众号选题Model.ets # 数据模型
│ │ └── AI公众号选题Service.ets # 业务服务
│ ├── AI公众号涨粉选题/
│ │ ├── AI公众号涨粉选题Page.ets
│ │ ├── AI公众号涨粉选题Model.ets
│ │ └── AI公众号涨粉选题Service.ets
│ └── ... (80+ 个 AI 应用)
项目使用了 @kit.ArkUI 和 @kit.ArkTS 两大核心 Kit。每个应用都遵循 MVP(Model-View-Presenter)风格的三层架构:Page(UI 层)、Model(数据层)、Service(业务逻辑层)。这种模式保证了代码的高内聚低耦合。
1.1.2 路由配置分析
应用的路由配置位于 entry/src/main/resources/base/profile/main_pages.json,其中注册了所有页面的路径。例如:
{
"src": [
"pages/Index",
"apps/AI公众号选题/AI公众号选题Page",
"apps/AI公众号涨粉选题/AI公众号涨粉选题Page",
...
]
}
Index 页面通过 router.pushUrl 跳转到具体应用页面,跳转逻辑在 apps.json 中配置,每个应用包含 icon、title、subtitle、page 路径和分类信息。
1.1.3 技术栈分析
- 语言:ArkTS(基于 TypeScript 的静态类型方言)
- UI 框架:ArkUI 声明式 UI
- 构建工具:Hvigor
- 依赖管理:oh-package.json5
- API Kit:@kit.ArkUI(UI 组件)、@kit.ArkTS(基础能力)
项目当前依赖配置(entry/oh-package.json5)为空,说明所有功能均基于 HarmonyOS 原生 API 实现,未引入第三方依赖。
1.2 ArkTS 语法约束
在开始编码之前,必须理解 ArkTS 与标准 TypeScript 的关键差异。以下是在开发过程中遇到的核心约束:
| 约束项 | 说明 | 影响范围 |
|---|---|---|
不支持 any/unknown |
必须显式指定类型 | 所有类型声明 |
| 不支持解构赋值 | 需使用临时变量逐字段操作 | 数据传递 |
不支持 Function.bind/call/apply |
this 遵循传统 OOP 风格 | 回调处理 |
不支持 for...in |
数组使用常规 for 循环 | 数据遍历 |
| 不支持索引签名 | 使用数组替代 | 字典数据结构 |
| 不支持对象字面量直接作为类型 | 需显式声明 class/interface | 数据模型 |
不支持 as const |
用显式类型标注替代 | 常量定义 |
this 仅能在实例方法中使用 |
静态方法和独立函数中禁用 | 事件处理 |
这些约束深刻影响了代码的组织方式。例如,在 AI公众号选题Page.ets 中,我们使用 Record<string, Object> 来存储输入数据,而不是使用解构赋值:
// ArkTS 不支持解构赋值,所以使用 Record 存储
@State inputData: Record<string, Object> = {};
// 通过 onChange 回调逐字段赋值,而非解构
TextInput({ placeholder: '请输入领域' })
.onChange((val: string) => {
this.inputData['领域'] = val;
});
1.3 需求理解与确认
1.3.1 原始需求
"AI公众号选题"应用的核心需求是:用户输入领域、目标读者和热点方向三个参数,系统自动生成包括选题列表、标题、切入角度、钩子、文章框架、预估阅读量、难度评级、标题变体、系列文章创意、发布时机和竞品分析等在内的完整选题方案。
1.3.2 边界确认
- 输入边界:三个必填字段(领域、目标读者、热点方向),均为文本输入
- 输出边界:13 个结构化输出字段,包含字符串数组和单值字符串
- 技术边界:当前阶段使用 Mock 数据模拟,后续可对接大模型 API
- 平台边界:仅支持 HarmonyOS 手机设备
1.3.3 需求理解
通过分析 AI公众号选题Model.ets 的数据模型,我们可以清晰地看到输出的完整结构:
export class AI公众号选题Data {
topics: string[] = []; // 推荐选题列表
title: string = ''; // 主标题
angle: string = ''; // 切入角度
hook: string = ''; // 钩子/开头
framework: string = ''; // 文章框架
estimated_reads: string = ''; // 预估阅读量
difficulty: string = ''; // 难度评级
title_variants: string[] = []; // 标题变体
topic: string = ''; // 主题
titles: string[] = []; // 标题列表
series_idea: string = ''; // 系列文章创意
timing: string = ''; // 发布时机
competitor_analysis: string = '';// 竞品分析
}
这个模型涵盖了选题策划的全部关键维度,从内容生产(标题、框架、角度)到运营策略(发布时机、竞品分析),再到效果预估(阅读量、难度),形成了一套完整的选题决策支持体系。
二、架构阶段(Architect)
架构阶段的目标是从共识文档到系统架构,再到模块设计和接口规范。良好的架构设计是应对复杂性和变化的关键。
2.1 整体架构设计
2.1.1 三层架构
AI公众号选题应用采用经典的三层架构:
┌─────────────────────────────────────┐
│ Presentation Layer │
│ AI公众号选题Page.ets (UI) │
│ - @Component 声明式 UI │
│ - @State 状态管理 │
│ - 用户交互与数据展示 │
└──────────────┬──────────────────────┘
│ 调用
┌──────────────▼──────────────────────┐
│ Service Layer │
│ AI公众号选题Service.ets (业务逻辑) │
│ - generateData() 核心方法 │
│ - 数据校验与转换 │
│ - Mock/API 数据生成 │
└──────────────┬──────────────────────┘
│ 返回
┌──────────────▼──────────────────────┐
│ Model Layer │
│ AI公众号选题Model.ets (数据模型) │
│ - AI公众号选题Data 数据类 │
│ - 字段类型定义 │
│ - 数据序列化 │
└─────────────────────────────────────┘
设计原则:
- 单向数据流:Page → Service → Model,数据通过返回值回传
- 职责单一:每个文件只负责一个关注点
- 接口隔离:Service 对 Page 暴露最小化接口
2.1.2 与项目架构的集成
该应用作为 MyApplication 项目中的一个子应用,需要与主框架集成:
- 路由集成:在
main_pages.json中注册页面路径 - 导航集成:通过
router.back()返回主页 - 数据集成:使用
getContext(this).resourceManager读取资源文件
2.2 模块详细设计
2.2.1 UI 层设计(AI公众号选题Page.ets)
UI 层采用 ArkUI 的声明式语法,整体结构分为三个区域:
Header 区域:包含返回按钮、标题和装饰元素
Row() {
Text('← 返回')
.fontSize(13)
.fontColor('#1A1A1A')
.onClick(() => { router.back() });
Blank();
Column() {
Text('📱 AI公众号选题')
.fontSize(17)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A');
Text('WHITEBOARD · 白板')
.fontSize(9)
.fontColor('#6B7280')
.margin({ top: 2 });
}
Blank();
Text('📋')
.fontSize(22);
}
.width('100%')
.padding({ left: 20, right: 20, top: 16, bottom: 14 })
.backgroundColor('#F9FAFB');
输入区域:三个输入字段,使用 TextInput 组件
结果展示区域:条件渲染,使用 if (this.showResult && this.resultData !== null) 控制显示
状态管理方面,使用了三个 @State 变量:
@State inputData: Record<string, Object> = {}; // 输入数据
@State resultData: AI公众号选题Data | null = null; // 结果数据
@State showResult: boolean = false; // 是否展示结果
这里有一个值得注意的 ArkTS 约束:@State 变量的类型必须显式声明。由于不支持 any 类型,我们使用了 Record<string, Object> 作为输入数据的容器类型。
2.2.2 数据模型层设计(AI公众号选题Model.ets)
数据模型层定义了 AI公众号选题Data 类,所有字段都有默认值并显式初始化:
export class AI公众号选题Data {
topics: string[] = [];
title: string = '';
angle: string = '';
hook: string = '';
framework: string = '';
estimated_reads: string = '';
difficulty: string = '';
title_variants: string[] = [];
topic: string = '';
titles: string[] = [];
series_idea: string = '';
timing: string = '';
competitor_analysis: string = '';
constructor() {
// 显式初始化确保所有字段有默认值
this.topics = [];
this.title = '';
// ... 其余字段初始化
}
}
设计考量:
- 默认值初始化:ArkTS 要求类字段必须有初始值,或者在构造函数中赋值
- 数组类型:
string[]是标准数组类型,不支持索引签名 - 不可变性:类实例化后,字段通过对象属性访问(
obj.field),不支持obj["field"]索引访问
2.2.3 服务层设计(AI公众号选题Service.ets)
服务层封装了核心业务逻辑,对外暴露 generateData 方法:
export class AI公众号选题Service {
private model: AI公众号选题Data;
constructor() {
this.model = new AI公众号选题Data();
}
generateData(input: Record<string, Object>): AI公众号选题Data {
let result: AI公众号选题Data = new AI公众号选题Data();
let fieldVal: string = String(input['field'] || '');
// Mock 数据生成
result.topics = ['示例数据1', '示例数据2', '示例数据3'];
result.title_variants = ['示例数据1', '示例数据2', '示例数据3'];
result.series_idea = '生成结果:' + fieldVal;
result.timing = '生成结果:' + fieldVal;
result.competitor_analysis = '生成结果:' + fieldVal;
return result;
}
}
设计要点:
- 解耦:Page 不直接操作 Model,通过 Service 中介
- 可测试性:Service 可以独立于 UI 进行单元测试
- 可扩展性:后续可替换为真实 API 调用,Page 层无需修改
2.3 数据流设计
用户输入 → inputData (Record) → Button Click →
service.generateData(inputData) →
构造 AI公众号选题Data 实例 →
填充 Mock 数据 →
返回 resultData →
赋值给 @State resultData →
UI 自动刷新 →
条件渲染展示结果
ArkUI 的响应式编程模型使得数据流自动驱动 UI 更新。当 @State resultData 被赋值时,UI 自动重新渲染,无需手动操作 DOM。
2.4 异常处理策略
// 在页面中,结果展示使用了安全的空值检查
if (this.showResult && this.resultData !== null) {
// 安全地访问 resultData 的字段
if (this.resultData.topics) {
ForEach(this.resultData.topics, ...);
}
}
ArkTS 的 catch 子句不支持类型标注(不支持 any/unknown),因此异常处理时省略类型标注:
try {
// 可能抛出异常的代码
} catch {
// ArkTS 中省略类型标注
console.error('发生错误');
}
三、原子化阶段(Atomize)
原子化阶段将任务分解为更小的、可管理的原子任务,便于高效执行和跟踪。
3.1 任务分解方法论
对于 AI公众号选题应用,我们将整个开发任务分解为以下原子任务:
3.1.1 基础设施任务
| 任务 ID | 任务描述 | 预估工时 | 依赖 |
|---|---|---|---|
| T-001 | 创建应用目录结构 | 0.5h | 无 |
| T-002 | 配置路由(main_pages.json) | 0.5h | T-001 |
| T-003 | 配置应用元数据(apps.json) | 0.5h | T-001 |
3.1.2 数据模型任务
| 任务 ID | 任务描述 | 预估工时 | 依赖 |
|---|---|---|---|
| T-004 | 定义 AI公众号选题Data 类 | 1h | T-001 |
| T-005 | 定义所有字段类型和默认值 | 0.5h | T-004 |
| T-006 | 实现构造函数初始化 | 0.5h | T-005 |
3.1.3 服务层任务
| 任务 ID | 任务描述 | 预估工时 | 依赖 |
|---|---|---|---|
| T-007 | 创建 AI公众号选题Service 类 | 1h | T-004 |
| T-008 | 实现 generateData 方法 | 2h | T-007 |
| T-009 | 实现 Mock 数据生成逻辑 | 1h | T-008 |
3.1.4 UI 层任务
| 任务 ID | 任务描述 | 预估工时 | 依赖 |
|---|---|---|---|
| T-010 | 实现 Header 组件 | 1h | T-001 |
| T-011 | 实现输入表单(三个字段) | 2h | T-010 |
| T-012 | 实现提交按钮 | 1h | T-011 |
| T-013 | 实现结果展示区域 | 2h | T-009, T-012 |
| T-014 | 实现条件渲染逻辑 | 1h | T-013 |
| T-015 | 样式优化和适配 | 1.5h | T-014 |
3.2 ArkTS 特有约束下的任务调整
在原子化分解过程中,需要针对 ArkTS 的语法约束进行任务调整:
3.2.1 数据展示的 ForEach 处理
由于 ArkTS 不支持 for...in 循环,遍历数组必须使用 ForEach 组件或常规 for 循环。在 UI 中,我们使用 ForEach:
// 展示选题列表
if (this.resultData.topics) {
ForEach(this.resultData.topics, (item: string, index: number) => {
Row() {
Text('• ')
.fontSize(12)
.fontColor('#666666');
Text(item)
.fontSize(12)
.fontColor('#333333');
}
.width('100%')
.padding({ top: 2, bottom: 2 });
}, (item: string, index: number) => index.toString());
}
ForEach 的第三个参数是键值生成函数,用于优化列表渲染性能。在 ArkTS 中,index.toString() 是推荐的键值生成方式。
3.2.2 条件渲染的 null 检查
ArkTS 中,条件渲染必须显式检查 null:
// ArkTS 不支持可选链操作符 ?. 的完整语义
// 需要显式检查 null
if (this.showResult && this.resultData !== null) {
// 安全访问
}
3.2.3 事件处理中的 this 绑定
ArkTS 不支持 Function.bind,但 Arrow Function 自动捕获外层 this:
// 使用箭头函数,无需 bind
.onClick(() => {
this.resultData = this.service.generateData(this.inputData);
this.showResult = true;
});
3.3 任务依赖图
T-001 (目录结构)
├── T-002 (路由配置)
├── T-003 (应用元数据)
└── T-004 (数据模型)
└── T-005 (字段类型)
└── T-006 (构造函数)
└── T-007 (Service 类)
└── T-008 (generateData)
└── T-009 (Mock 数据)
T-010 (Header)
└── T-011 (输入表单)
└── T-012 (提交按钮)
└── T-013 (结果展示)
└── T-014 (条件渲染)
└── T-015 (样式优化)
3.4 原子化任务的优势
- 并行开发:T-002/T-003/T-004 可以并行推进
- 风险隔离:单个任务失败不影响整体
- 精确评估:每个任务 0.5-2h,便于进度跟踪
- 质量可控:每个任务可独立验证
四、审批阶段(Approve)
审批阶段对前面阶段的成果进行审核和批准,确保符合质量要求。
4.1 ArkTS 语法合规审查
在审批阶段,代码必须通过 ArkTS 编译器的严格检查。以下是关键的审查点:
4.1.1 类型安全检查
审查规则:所有变量必须有显式类型,禁止使用 any/unknown。
通过示例:
// ✅ 正确:显式类型声明
@State inputData: Record<string, Object> = {};
@State resultData: AI公众号选题Data | null = null;
private service: AI公众号选题Service = new AI公众号选题Service();
// ❌ 错误:隐式 any 类型
// @State inputData = {}; // 编译错误
4.1.2 类声明规范
审查规则:类字段必须在类声明中初始化,构造函数中不能声明新字段。
通过示例:
export class AI公众号选题Data {
// ✅ 正确:在类声明中声明并初始化所有字段
topics: string[] = [];
title: string = '';
angle: string = '';
// ...
constructor() {
// ✅ 正确:构造函数中只赋值,不声明
this.topics = [];
this.title = '';
this.angle = '';
// ...
}
}
4.1.3 对象字面量使用规范
审查规则:对象字面量必须有可推断的类型,不能直接用作类型声明。
通过示例:
// ✅ 正确:使用 Record 类型
@State inputData: Record<string, Object> = {};
// ✅ 正确:在 ForEach 中使用的数组字面量元素类型一致
ForEach(['数据源','分析中','就绪'], (item: string) => { ... });
4.1.4 函数类型规范
审查规则:使用箭头函数替代函数表达式,不支持函数声明上的属性。
通过示例:
// ✅ 正确:使用箭头函数作为回调
.onChange((val: string) => {
this.inputData['领域'] = val;
});
// ✅ 正确:ForEach 中使用箭头函数
ForEach(this.resultData.topics, (item: string, index: number) => {
// ...
}, (item: string, index: number) => index.toString());
4.2 架构合规审查
4.2.1 三层架构检查
规则:Page 层不能直接修改 Model 层数据,必须通过 Service 层。
通过检查:
// ✅ 正确:Page 通过 Service 获取数据
onClick(() => {
this.resultData = this.service.generateData(this.inputData);
this.showResult = true;
});
// ❌ 错误:Page 直接构造 Model
// this.resultData = new AI公众号选题Data();
// this.resultData.topics = [...]; // 违反分层原则
4.2.2 路由配置检查
规则:所有页面必须在 main_pages.json 中注册。
检查通过:AI公众号选题Page 已在 main_pages.json 中注册为 "apps/AI公众号选题/AI公众号选题Page"。
4.2.3 资源引用检查
规则:UI 中的文字应使用 $r 引用资源文件,而非硬编码。
当前状态:由于项目规模较小,部分文字直接使用了字面量。在正式发布前,建议将常用文字移至 resources/base/element/string.json 中。
4.3 验收标准
4.3.1 功能验收
| 验收项 | 标准 | 状态 |
|---|---|---|
| 输入字段 | 三个输入框正常工作 | ✅ |
| 数据生成 | 点击按钮后生成数据 | ✅ |
| 结果展示 | 13 个字段完整展示 | ✅ |
| 返回导航 | 点击返回可回到主页 | ✅ |
| 空状态处理 | 无数据时不展示结果 | ✅ |
4.3.2 代码质量验收
| 验收项 | 标准 | 状态 |
|---|---|---|
| 类型安全 | 无 any/unknown 类型 | ✅ |
| 编译通过 | 无编译错误 | ✅ |
| 代码规范 | 遵循 ArkTS 语法约束 | ✅ |
| 命名规范 | 类名大写开头,变量驼峰 | ✅ |
4.3.3 ArkTS 专有检查清单
□ 无解构赋值语句
□ 无 Function.bind/call/apply 调用
□ 无 for...in 循环
□ 无索引签名
□ 无对象字面量直接作为类型
□ 所有类字段显式初始化
□ 所有 import 在文件顶部
□ 无 as const 断言
□ catch 子句无类型标注
□ 箭头函数替代函数表达式
五、自动化执行阶段(Automate)
自动化执行阶段利用自动化工具和流程执行任务,提高开发效率和代码质量。
5.1 代码生成自动化
5.1.1 数据模型代码生成
对于 AI公众号选题Data 这样的数据模型,可以编写代码生成模板,自动生成重复的字段声明和构造函数初始化代码:
// 模板示例(伪代码)
// 输入:字段列表
// 输出:自动生成的类代码
// 字段定义
const FIELDS = [
{ name: 'topics', type: 'string[]', default: '[]' },
{ name: 'title', type: 'string', default: "''" },
{ name: 'angle', type: 'string', default: "''" },
// ...
];
// 自动生成代码
function generateModelClass(fields) {
let classCode = 'export class AI公众号选题Data {\n';
for (let f of fields) {
classCode += ` ${f.name}: ${f.type} = ${f.default};\n`;
}
classCode += '\n constructor() {\n';
for (let f of fields) {
classCode += ` this.${f.name} = ${f.default};\n`;
}
classCode += ' }\n}\n';
return classCode;
}
5.1.2 UI 代码模板化
结果展示区域的代码具有高度重复性——每个字段都使用类似的 Row/Text 结构。我们可以通过数据驱动的方式来减少重复代码:
// 定义展示字段配置
interface DisplayField {
label: string;
key: string;
isArray: boolean;
}
const DISPLAY_FIELDS: DisplayField[] = [
{ label: 'Title', key: 'title', isArray: false },
{ label: 'Angle', key: 'angle', isArray: false },
{ label: 'Hook', key: 'hook', isArray: false },
{ label: 'Framework', key: 'framework', isArray: false },
{ label: 'Estimated reads', key: 'estimated_reads', isArray: false },
{ label: 'Difficulty', key: 'difficulty', isArray: false },
{ label: 'Topic', key: 'topic', isArray: false },
{ label: 'Series idea', key: 'series_idea', isArray: false },
{ label: 'Timing', key: 'timing', isArray: false },
{ label: 'Competitor analysis', key: 'competitor_analysis', isArray: false },
];
// 使用 ForEach 自动生成展示行
ForEach(DISPLAY_FIELDS, (field: DisplayField) => {
Row() {
Text(field.label + ': ')
.fontSize(12)
.fontWeight(FontWeight.Medium)
.fontColor('#666666');
// 动态访问字段值(ArkTS 中需使用类型转换)
Text((this.resultData as Record<string, Object>)[field.key] as string)
.fontSize(12)
.fontColor('#333333');
}
.width('100%')
.padding({ top: 4, bottom: 4 });
}, (field: DisplayField) => field.key);
注意:在 ArkTS 中,由于不支持索引访问类型(
obj["field"]),上述代码中动态字段访问需要谨慎处理。标准做法是直接访问具名字段。
5.2 构建自动化
5.2.1 Hvigor 构建配置
HarmonyOS 应用使用 Hvigor 作为构建工具,构建配置位于项目根目录和模块目录的 build-profile.json5 中。构建过程自动处理:
- ArkTS 编译:将
.ets文件编译为方舟字节码 - 资源编译:处理
resources目录下的资源文件 - 打包:生成 HAP(HarmonyOS Ability Package)包
5.2.2 持续集成流程
对于团队开发,建议配置以下 CI 流程:
# 伪代码:CI 流程配置
stages:
- lint: # ArkTS 语法检查
- hvigor lint
- build: # 编译构建
- hvigor assembleDebug
- test: # 单元测试
- hvigor test
- deploy: # 部署到测试环境
- hvigor assembleRelease
5.3 数据 Mock 自动化
当前 Service 层使用 Mock 数据,后续可以结构化地生成更真实的模拟数据:
export class AI公众号选题Service {
// Mock 数据模板
private mockTemplates: Record<string, string[]> = {
topics: [
'2024年最值得关注的AI趋势',
'如何用ChatGPT提升10倍工作效率',
'从0到1搭建个人知识体系',
// ...
],
angles: [
'从行业趋势切入,结合具体案例',
'从用户痛点出发,提供解决方案',
'从数据报告出发,分析深层原因',
// ...
],
hooks: [
'你知道吗?90%的人都忽略了这一点',
'如果你只有时间读一篇文章,请读这篇',
'我花了3个月时间,终于搞懂了这个问题',
// ...
],
};
generateMockData(input: Record<string, Object>): AI公众号选题Data {
let result: AI公众号选题Data = new AI公众号选题Data();
let field: string = String(input['领域'] || '');
let reader: string = String(input['目标读者'] || '');
let hot: string = String(input['热点方向'] || '');
// 根据输入生成更真实的 Mock 数据
result.topics = this.pickRandom(this.mockTemplates.topics, 3);
result.title = `【${field}】${this.pickRandom(this.mockTemplates.hooks, 1)[0]}`;
result.angle = `针对${reader},从${hot}角度切入`;
// ...
return result;
}
private pickRandom(arr: string[], count: number): string[] {
let result: string[] = [];
let copy: string[] = arr.slice();
for (let i: number = 0; i < count && copy.length > 0; i++) {
let idx: number = Math.floor(Math.random() * copy.length);
result.push(copy[idx]);
copy.splice(idx, 1);
}
return result;
}
}
5.4 测试自动化
5.4.1 单元测试
Service 层可以独立编写单元测试:
// 单元测试示例(使用 HarmonyOS 测试框架)
import { describe, it, expect } from '@ohos/hypium';
import { AI公众号选题Service } from '...';
describe('AI公众号选题Service', () => {
it('generateData_should_return_valid_data', () => {
let service = new AI公众号选题Service();
let input: Record<string, Object> = {
'领域': '人工智能',
'目标读者': '技术从业者',
'热点方向': '大模型'
};
let result = service.generateData(input);
expect(result.topics.length).assertGreaterThan(0);
expect(result.title).assertNotEmpty();
expect(result.angle).assertNotEmpty();
});
});
5.4.2 UI 自动化测试
ArkUI 支持 UI 自动化测试,可以验证组件的交互行为:
// UI 测试示例
import { UIAbility } from '@kit.AbilityKit';
import { Driver, ON } from '@kit.UITestKit';
describe('AI公众号选题Page', () => {
it('should_display_result_after_click', async () => {
let driver = await Driver.create();
// 输入领域
let inputField = await driver.findComponent(ON.text('请输入领域'));
await inputField.inputText('人工智能');
// 点击按钮
let button = await driver.findComponent(ON.text('📱 📋 整理白板'));
await button.click();
// 验证结果展示
let result = await driver.findComponent(ON.text('📋 白板内容'));
expect(result).assertIsTrue();
});
});
六、评估阶段(Assess)
评估阶段对整个过程和成果进行评估,总结经验教训,为后续项目提供参考。
6.1 技术选型评估
6.1.1 ArkTS vs TypeScript
| 维度 | ArkTS | TypeScript | 对项目的影响 |
|---|---|---|---|
| 类型安全 | 更严格,无 any | 灵活,允许 any | 代码更可靠,但开发效率略低 |
| 运行时性能 | 编译为方舟字节码,性能优 | 解释执行 | 用户体验更好 |
| 生态系统 | 仅 HarmonyOS | 全平台 | 第三方库支持有限 |
| 学习曲线 | 需适应新约束 | 标准 | 团队需额外培训 |
评价:对于 HarmonyOS 原生应用开发,ArkTS 的严格类型系统在长期维护中带来了显著收益。虽然初期开发需要适应其约束,但编译阶段的错误检查有效避免了运行时异常。
6.1.2 架构模式评估
MVP(Model-View-Presenter)模式在本次项目中表现良好:
- 优势:职责清晰,各层独立可测试
- 改进空间:对于小型应用,可以简化 Service 层,将简单逻辑直接放在 Page 中
- 建议:当应用复杂度增加时,可以考虑引入状态管理框架
6.2 代码质量评估
6.2.1 代码量统计
AI公众号选题Page.ets: ~195 行
AI公众号选题Model.ets: ~31 行
AI公众号选题Service.ets: ~23 行
总计: ~249 行
6.2.2 圈复杂度分析
AI公众号选题Page.ets:包含 1 个@Component、1 个build()方法、多个条件渲染分支AI公众号选题Model.ets:纯数据类,圈复杂度为 1AI公众号选题Service.ets:包含 1 个公开方法,圈复杂度为 1
6.2.3 代码复用率
- 三个文件之间无重复代码(职责分离良好)
- 与其他 AI 应用共享
更多推荐

所有评论(0)