HarmonyOS AI 应用开发实战:考研择校分析系统
本文基于 HarmonyOS + ArkTS 的 Model-Service-Page 架构,详细解析考研择校分析 AI 应用的完整开发流程,涵盖需求分析、架构设计、提示词工程、核心实现、性能优化等全链路技术要点。
一、项目背景与需求分析
1.1 行业痛点与用户需求
考研择校是每年数百万考研学子面临的首要难题。根据教育部数据,2025年全国硕士研究生报名人数达到438万,而录取率仅约24%。在如此激烈的竞争环境下,科学择校成为决定考研成败的关键因素之一。然而,当前考研择校面临以下痛点:
- 信息过载:全国800多所高校、数千个硕士点,考生难以全面获取和分析各院校的招生数据、报录比、历年分数线等信息。
- 匹配模糊:考生往往缺乏对自身条件与院校要求的精准匹配分析工具,仅凭经验和直觉选择院校,导致"高攀"或"低就"。
- 动态变化:各院校的招生政策、专业设置、考试科目每年都在变化,考生需要实时掌握最新信息。
- 个性化不足:通用的择校建议难以满足不同专业背景、不同成绩水平、不同地区偏好的个性化需求。
基于以上痛点,我们设计并开发了一款基于 HarmonyOS 的考研择校分析 AI 应用,旨在利用大语言模型的能力,为考生提供个性化的院校分析与推荐服务。

1.2 产品目标与功能定位
本应用的核心目标是帮助考研学子快速、科学地完成择校决策。具体功能需求包括:
- 信息输入:支持用户输入专业、地区偏好、预估分数等关键信息
- AI 分析:基于用户输入,利用 AI 模型生成院校分层分析、报考建议
- 结果展示:以清晰的可视化方式展示院校分析结果,包括院校梯队、难度评估、匹配度等
- 即时交互:一键生成分析结果,操作简便,响应迅速
1.3 技术选型考量
| 技术维度 | 选择方案 | 选择理由 |
|---|---|---|
| 操作系统 | HarmonyOS NEXT | 国产自主可控,分布式能力,跨设备协同 |
| 开发语言 | ArkTS | 基于 TypeScript 的声明式 UI 语言,学习成本低,类型安全 |
| UI 框架 | ArkUI | 声明式 UI 范式,支持响应式布局,组件丰富 |
| 架构模式 | Model-Service-Page | 职责清晰,易于测试和维护,适合 AI 应用场景 |
| AI 能力 | 大语言模型 API | 利用 LLM 的语义理解和生成能力实现智能分析 |
二、技术架构设计
2.1 Model-Service-Page 架构总览
本应用采用经典的三层架构模式------Model-Service-Page,各层职责明确:
┌─────────────────────────────────────────────────────────┐
│ Page 层 │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 考研择校分析Page.ets │ │
│ │ - 用户输入采集与校验 │ │
│ │ - 结果展示与交互响应 │ │
│ │ - 状态管理 (inputData, resultData, showResult) │ │
│ └──────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Service 层 │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 考研择校分析Service.ets │ │
│ │ - 业务逻辑编排 │ │
│ │ - AI 提示词构建与调用 │ │
│ │ - 数据封装与返回 │ │
│ └──────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Model 层 │
│ ┌──────────────────────────────────────────────────┐ │
│ │ GradSchoolData │ │
│ │ - 数据字段定义与默认值 │ │
│ │ - 类型约束与数据校验 │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
2.2 数据流设计
应用的数据流采用单向数据流模式,确保数据可预测、可追踪:
用户操作 → Page 采集输入 → 构建 inputData Record
↓
Service.generateData(input) 被调用
↓
构建 Prompt → 调用 AI API → 解析返回结果
↓
封装为 Model 实例 → 返回给 Page
↓
Page 更新 @State 变量 → UI 自动刷新
2.3 Model 层设计详解
Model 层是整个应用的数据基础。在 GradSchoolData 类中,我们定义了所有需要存储和展示的数据字段:
typescript
export class GradSchoolData {
major: string = '' // 用户输入的专业
region_pref: string = '' // 地区偏好
estimated_score: string = '' // 预估分数
tiers: Record<string, string>[] = [] // 院校梯队分析(数组,每个元素包含院校名称和对应分析)
advice: string = '' // 综合报考建议
constructor() {
this.major = ''
this.region_pref = ''
this.estimated_score = ''
this.tiers = []
this.advice = ''
}
}
设计要点分析:
-
字段默认值初始化:ArkTS 要求所有字段在声明时或在构造函数中初始化。这里采用"声明时初始化 + 构造函数双重初始化"的策略,确保无论编译器如何优化,字段都有默认值。
-
Record<string, string>\[\] 类型:使用 ArkTS 支持的 Record 类型来表示键值对数组,用于存储院校名称和对应分析内容的映射关系。这种类型在 ArkTS 中是被明确支持的(Partial、Required、Readonly、Record 是例外允许的实用类型)。
-
字符串类型为主:考虑到 AI 生成的文本内容具有不确定性,大部分字段使用 string 类型,避免了复杂类型转换的麻烦。
2.4 Service 层设计详解
Service 层封装了 AI 调用的核心业务逻辑:
typescript
import { GradSchoolData } from './考研择校分析Model'
export class GradSchoolService {
private model: GradSchoolData
constructor() {
this.model = new GradSchoolData()
}
generateData(input: Record<string, Object>): GradSchoolData {
let result: GradSchoolData = new GradSchoolData()
// 1. 构建 Prompt
// 2. 调用 AI API
// 3. 解析与封装结果
return result
}
}
设计要点:
- 单例模式 :Service 实例在 Page 中创建,通过
private service: GradSchoolService = new GradSchoolService()保持单例。 - 输入输出规范 :
generateData方法接受Record<string, Object>作为输入,返回GradSchoolData实例,保持接口的统一性。 - 异常隔离:所有 AI 调用逻辑封装在 Service 层,Page 层无需关心具体实现,便于后续替换 AI 模型或降级处理。
2.5 Page 层设计详解
Page 层是用户交互的入口,负责 UI 渲染和事件处理:
typescript
@Entry
@Component
struct GradSchoolPage {
@State inputData: Record<string, Object> = {}
@State resultData: GradSchoolData | null = null
@State showResult: boolean = false
private service: GradSchoolService = new GradSchoolService()
build() {
Column() {
// Header 部分
Row() { /* 返回按钮 + 标题 */ }
// 内容区域
Scroll() {
Column() {
// 输入区域
// 生成按钮
// 结果展示区域
}
}
}
}
}
状态管理策略:
@State inputData:存储用户输入,通过onChange事件实时更新@State resultData:存储 AI 生成结果,初始为 null,生成后赋值@State showResult:控制结果区域的显示/隐藏,使用if条件渲染
三、AI 提示词工程原理
3.1 提示词设计原则
在 AI 应用中,提示词(Prompt)的质量直接决定了生成结果的质量。我们遵循以下设计原则:
3.1.1 角色设定(Role Setting)
为 AI 设定明确的角色身份,使其在特定上下文中生成更专业的内容:
你是一位资深的考研择校规划师,拥有10年以上的考研辅导经验,熟悉全国各大高校的招生政策、专业实力和录取难度。
3.1.2 结构化输出(Structured Output)
指定输出格式,确保 AI 生成的内容能够被程序正确解析:
请按照以下结构输出分析结果:
1. 院校梯队分析(按冲刺院校、稳妥院校、保底院校三个梯队,每个梯队推荐2-3所院校)
2. 综合报考建议(包括备考策略、时间规划、注意事项等)
3.1.3 上下文注入(Context Injection)
将用户输入的关键信息注入 Prompt,使 AI 能够基于具体条件生成个性化建议:
用户信息:
- 专业:{major}
- 地区偏好:{region_pref}
- 预估分数:{estimated_score}
3.2 提示词模板示例
typescript
buildPrompt(input: Record<string, Object>): string {
let major: string = input['major'] as string
let region: string = input['region_pref'] as string
let score: string = input['estimated_score'] as string
return `你是一位资深的考研择校规划师。请根据以下用户信息,提供个性化的院校分析。
用户信息:
- 专业:${major}
- 地区偏好:${region}
- 预估分数:${score}
请按照以下 JSON 格式输出结果:
{
"tiers": [
{"name": "冲刺院校", "schools": "院校名称及分析"},
{"name": "稳妥院校", "schools": "院校名称及分析"},
{"name": "保底院校", "schools": "院校名称及分析"}
],
"advice": "综合报考建议"
}`
}
3.3 输出解析策略
AI 返回的结果通常是 JSON 或 Markdown 格式的文本,需要解析后填充到 Model 中:
typescript
parseResponse(response: string): GradSchoolData {
let result: GradSchoolData = new GradSchoolData()
try {
let parsed: Object = JSON.parse(response)
// 安全地提取字段
if (parsed['tiers']) {
result.tiers = parsed['tiers']
}
if (parsed['advice']) {
result.advice = parsed['advice']
}
} catch (e) {
// 解析失败时的降级处理
result.advice = response
}
return result
}
四、核心功能实现详解
4.1 用户输入采集
输入采集使用 ArkUI 的 TextInput 组件,通过 onChange 事件实时更新 inputData:
typescript
Text('专业')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
.margin({ top: 12, bottom: 4 })
TextInput({ placeholder: '请输入专业' })
.fontSize(14)
.height(44)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.padding({ left: 12, right: 12 })
.onChange((val: string) => { this.inputData['major'] = val })
设计考量:
- 占位符提示 :通过
placeholder属性提供输入提示,降低用户使用门槛 - 统一高度与圆角:44px 高度 + 8px 圆角,符合移动端交互规范
- 白色背景:在浅灰色背景(#F8FAFC)上,白色输入框形成清晰的视觉层次
- 实时响应 :
onChange事件在每次输入变化时触发,确保数据始终与 UI 同步
4.2 AI 生成按钮交互
typescript
Button('AI 生成')
.width('100%')
.height(48)
.backgroundColor('#3B82F6')
.borderRadius(12)
.fontColor('#FFFFFF')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 16 })
.onClick(() => {
this.resultData = this.service.generateData(this.inputData)
this.showResult = true
})
交互设计要点:
- 全宽按钮:宽度 100%,符合移动端操作习惯,便于点击
- 品牌蓝色:#3B82F6 是典型的"行动号召"蓝色,传达专业和信任感
- 加载状态:实际应用中可以增加加载状态(如旋转指示器),避免用户重复点击
- 结果触发 :点击后立即更新
resultData和showResult,触发 UI 重新渲染
4.3 结果条件渲染
使用 ArkUI 的 if 条件渲染指令,在结果未生成时隐藏结果区域:
typescript
if (this.showResult && this.resultData !== null) {
Text('生成结果')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
.width('100%')
.margin({ top: 16, bottom: 8 })
Text('择校分析')
.fontSize(14)
.fontColor($r('app.color.text_secondary'))
.width('100%')
.margin({ bottom: 16 })
}
条件渲染的优势:
- 性能优化:未生成结果时,结果区域的组件树不会被创建,减少内存占用
- 用户体验:结果区域在生成前不可见,避免用户看到空数据产生困惑
- 状态清晰 :
showResult布尔值清晰地表达了"是否已生成结果"的状态语义
4.4 数据流完整闭环
从用户输入到结果展示的完整数据流如下:
用户输入专业 → inputData['major'] = '计算机科学与技术'
用户输入地区 → inputData['region_pref'] = '北京'
用户输入分数 → inputData['estimated_score'] = '380'
用户点击"AI 生成" → 触发 onClick
↓
service.generateData(inputData) 被调用
↓
构建 Prompt → 调用 AI API → 解析结果
↓
返回 GradSchoolData 实例
↓
[this.resultData](this.resultData) = GradSchoolData 实例
this.showResult = true
↓
UI 自动重新渲染
↓
显示"生成结果"区域 → 展示院校分析、建议等
五、用户体验优化
5.1 视觉层次设计
页面采用清晰的视觉层次结构:
┌─────────────────────────────────┐
│ ← 返回 考研择校分析 │ ← Header
├─────────────────────────────────┤
│ 输入信息 │ ← Section Title
│ ┌─────────────────────────┐ │
│ │ 专业 │ │
│ │ [输入框] │ │ ← Input Fields
│ │ 地区偏好 │ │
│ │ [输入框] │ │
│ │ 预估分数 │ │
│ │ [输入框] │ │
│ └─────────────────────────┘ │
│ ┌─────────────────────────┐ │
│ │ AI 生成 │ │ ← Action Button
│ └─────────────────────────┘ │
│ 生成结果 │ ← Result Section
│ 择校分析内容... │
└─────────────────────────────────┘
5.2 响应式适配
通过 Scroll 组件包裹内容区域,确保在不同屏幕尺寸下都能正常显示:
typescript
Scroll() {
Column() {
// 所有内容
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 40 })
}
.layoutWeight(1)
5.3 颜色资源管理
使用 $r 引用资源文件中的颜色值,便于主题切换和统一管理:
typescript
.fontColor($r('app.color.text_primary')) // 主文本颜色
.fontColor($r('app.color.text_secondary')) // 次要文本颜色
.backgroundColor('#F8FAFC') // 页面背景色
.backgroundColor('#FFFFFF') // 输入框背景色
5.4 性能优化实践
5.4.1 组件按需加载
通过 if 条件渲染,避免不必要的组件创建:
typescript
if (this.showResult && this.resultData !== null) {
// 只有在有结果时才渲染结果区域
}
5.4.2 输入防抖
在实际应用中,可以为输入添加防抖处理,避免频繁的 onChange 触发:
typescript
let debounceTimer: number = -1
function onInputChange(val: string, key: string): void {
clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
this.inputData[key] = val
}, 300)
}
5.4.3 结果缓存
对于相同的输入组合,可以缓存 AI 生成结果,避免重复调用:
typescript
private resultCache: Map<string, GradSchoolData> = new Map()
generateData(input: Record<string, Object>): GradSchoolData {
let cacheKey: string = JSON.stringify(input)
if (this.resultCache.has(cacheKey)) {
return this.resultCache.get(cacheKey)!
}
let result: GradSchoolData = // AI 调用...
this.resultCache.set(cacheKey, result)
return result
}
六、性能优化与最佳实践
6.1 ArkTS 语法约束适配
在开发过程中,需要特别注意 ArkTS 的语法约束:
6.1.1 类型安全
ArkTS 不支持 any 和 unknown 类型,所有变量必须显式指定类型:
typescript
// 错误:不支持 any 类型
// let data: any = {}
// 正确:使用 Record 或具体类型
let inputData: Record<string, Object> = {}
6.1.2 构造函数初始化
ArkTS 不支持在构造函数中声明类字段,必须在类声明内部声明:
typescript
// 正确
export class GradSchoolData {
major: string = ''
constructor() {
this.major = '' // 构造函数中重新赋值是允许的
}
}
// 错误:不支持在构造函数中声明
// export class GradSchoolData {
// constructor() {
// this.major = '' // 未在类中声明
// }
// }
6.1.3 箭头函数使用
ArkTS 不支持函数表达式,必须使用箭头函数:
typescript
// 正确
.onClick(() => {
this.resultData = this.service.generateData(this.inputData)
})
// 错误:不支持函数表达式
// .onClick(function() {
// this.resultData = ...
// })
6.2 内存管理优化
6.2.1 对象复用
避免频繁创建新对象,减少 GC 压力:
typescript
// 优化前:每次生成都创建新对象
let result: GradSchoolData = new GradSchoolData()
// 优化:复用已有对象,只更新字段
let result: GradSchoolData = this.resultData ?? new GradSchoolData()
6.2.2 数组操作优化
使用 ForEach 代替 for...in 循环:
typescript
// 正确:使用 ForEach 遍历数组
ForEach(this.resultData.tiers, (item: Record<string, string>, index: number) => {
Text(item['name'])
Text(item['schools'])
}, (item: Record<string, string>, index: number) => {
return index.toString()
})
// 错误:不支持 for...in
// for (let key in this.resultData) { ... }
6.3 网络请求优化
6.3.1 超时控制
为 AI API 调用设置超时,避免长时间等待:
typescript
async generateData(input: Record<string, Object>): Promise<GradSchoolData> {
let controller = new AbortController()
let timeoutId = setTimeout(() => controller.abort(), 30000) // 30秒超时
try {
let response = await fetch('AI_API_URL', {
signal: controller.signal
})
// 处理响应
} finally {
clearTimeout(timeoutId)
}
}
6.3.2 错误重试
实现指数退避的重试机制:
typescript
async function callWithRetry(prompt: string, maxRetries: number = 3): Promise<string> {
for (let i = 0; i < maxRetries; i++) {
try {
let response = await callAI(prompt)
return response
} catch (e) {
if (i === maxRetries - 1) throw e
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)))
}
}
return ''
}
6.4 代码组织最佳实践
6.4.1 文件命名规范
- Model 文件:
考研择校分析Model.ets - Service 文件:
考研择校分析Service.ets - Page 文件:
考研择校分析Page.ets
6.4.2 导入规范
所有 import 语句必须在文件开头:
typescript
// 正确:import 在文件最前面
import { GradSchoolData } from './考研择校分析Model'
import { GradSchoolService } from './考研择校分析Service'
import { router } from '@kit.ArkUI'
// 业务代码...
6.4.3 模块化设计
将业务逻辑、数据处理、UI 展示分离到不同的类和文件中,提高代码的可维护性和可测试性。
七、总结与展望
7.1 项目成果总结
通过本项目的开发实践,我们成功构建了一个基于 HarmonyOS 的考研择校分析 AI 应用,实现了以下核心目标:
- 架构清晰:采用 Model-Service-Page 三层架构,各层职责明确,代码可维护性强
- 交互流畅:基于 ArkUI 声明式框架,实现即时响应式 UI 更新
- AI 赋能:利用大语言模型的语义理解与生成能力,提供个性化院校分析
- 类型安全:充分利用 ArkTS 的静态类型系统,在编译期捕获潜在错误
7.2 技术经验沉淀
Model-Service-Page 架构优势:
- 关注点分离:数据模型、业务逻辑、UI 展示完全解耦
- 可测试性:Service 层可以独立测试,无需依赖 UI 环境
- 可扩展性:新增 AI 模型或替换现有模型时,只需修改 Service 层
- 复用性:Model 类可以在多个页面或服务间共享
ArkTS 开发经验:
- 静态类型系统是双刃剑:虽然增加了类型约束,但能显著减少运行时错误
- 声明式 UI 开发效率高:状态驱动 UI 更新,无需手动操作 DOM
- 资源引用机制($r)便于统一管理主题和国际化
7.3 未来优化方向
短期优化:
- 加载动效:增加 AI 生成过程中的加载动画,提升等待体验
- 输入校验:增加前端输入校验,确保关键字段非空
- 结果分享:支持将分析结果分享为图片或文本
中期规划:
- 历史记录:保存用户的查询历史,支持对比分析
- 多轮对话:支持在分析结果基础上继续追问和细化
- 数据可视化:使用图表组件展示院校对比数据
长期愿景:
- 知识图谱:构建院校-专业-导师的知识图谱,提供更精准的匹配
- 社区功能:引入用户分享和评价机制,形成择校经验社区
- 跨端协同:利用 HarmonyOS 分布式能力,在手机、平板、智慧屏间无缝切换
7.4 给开发者的建议
- 先理解 ArkTS 约束再编码:ArkTS 相比标准 TypeScript 有较多约束,建议在开发前仔细阅读官方文档中的语法约束部分
- 善用 @State 响应式编程:ArkUI 的响应式系统是开发效率的关键,合理使用 @State、@Link 等装饰器
- Prompt 工程是核心:AI 应用的质量很大程度上取决于提示词设计,建议多轮迭代优化
- 关注鸿蒙生态演进:HarmonyOS 生态在快速发展,持续关注 API 更新和社区最佳实践
本文通过考研择校分析应用的完整开发实践,详细阐述了 HarmonyOS + ArkTS + AI 的全栈开发流程。希望本文能为正在探索鸿蒙 AI 应用开发的同行提供有价值的参考和借鉴。