HarmonyOS AI 应用开发实战:简历项目经历改写系统
本文基于 HarmonyOS + ArkTS 的 Model-Service-Page 架构,详细解析简历项目经历改写 AI 应用的完整开发流程,涵盖求职痛点分析、架构设计、STAR法则提示词工程、核心实现、性能优化等全链路技术要点。

一、项目背景与需求分析
1.1 求职简历的痛点
在当今竞争激烈的就业市场中,一份优秀的简历是求职者获得面试机会的关键。然而,根据招聘平台的数据显示,超过 80% 的简历在投递后未能获得面试机会,其中最主要的原因为项目经历描述不够专业、缺乏量化成果、与岗位需求不匹配。
简历项目经历写作面临以下核心痛点:
- STAR 法则缺失:大多数求职者不知道如何运用 STAR 法则(Situation 情境、Task 任务、Action 行动、Result 结果)来结构化描述项目经历
- 量化不足:描述过于笼统,缺乏具体的数据支撑,如"提升了系统性能"而非"将系统响应时间从 500ms 降低到 100ms"
- 关键词缺失:简历中的关键词与目标岗位的 JD(Job Description)不匹配,导致筛选系统无法识别
- 表达冗长:描述不够精炼,难以在短时间内吸引招聘官的注意力
1.2 产品功能定位
本应用旨在利用 AI 大语言模型的能力,帮助求职者将原始的项目经历描述改写为专业、量化、匹配岗位需求的 STAR 版本。核心功能包括:
- STAR 版本改写:将原始描述按照 STAR 法则重新组织,生成结构化、专业的项目经历描述
- 量化建议:识别可以量化的环节,提供具体的量化指标建议
- 关键词替换:根据目标岗位方向,提供关键词替换建议
- 优化说明:解释改写的原因和优化点,帮助用户学习简历写作技巧
1.3 技术选型
| 维度 | 方案 | 说明 |
|---|---|---|
| 平台 | HarmonyOS NEXT | 国产操作系统,全场景支持 |
| 语言 | ArkTS | 静态类型安全,声明式 UI |
| 框架 | ArkUI | 响应式布局,组件丰富 |
| 架构 | Model-Service-Page | 三层分离,职责清晰 |
| AI | 大语言模型 | STAR 法则改写 + 关键词优化 |
二、技术架构设计
2.1 架构总览
┌─────────────────────────────────────────────────────────────────┐
│ Page 层 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ResumeProjectPage │ │
│ │ ├── 输入:原始描述、岗位方向 │ │
│ │ ├── 按钮:AI 生成 │ │
│ │ └── 结果:STAR版本、量化建议、关键词替换、优化说明 │ │
│ └──────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Service 层 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ResumeProjectService │ │
│ │ ├── Prompt 构建(STAR法则 + 岗位关键词) │ │
│ │ ├── AI API 调用 │ │
│ │ ├── 响应解析与数据映射 │ │
│ │ └── 降级策略 │ │
│ └──────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Model 层 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ResumeProjectData │ │
│ │ ├── original: string(原始描述) │ │
│ │ ├── role_direction: string(岗位方向) │ │
│ │ ├── star_version: string(STAR版本) │ │
│ │ ├── quantify_tips: string[](量化建议) │ │
│ │ ├── keyword_swaps: Record<string, string>(关键词替换) │ │
│ │ └── improvement: string(优化说明) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
2.2 Model 层:数据模型设计
typescript
export class ResumeProjectData {
original: string = ''
role_direction: string = ''
star_version: string = ''
quantify_tips: string[] = []
keyword_swaps: Record<string, string> = {}
improvement: string = ''
constructor() {
this.original = ''
this.role_direction = ''
this.star_version = ''
this.quantify_tips = []
this.keyword_swaps = {}
this.improvement = ''
}
}
字段设计分析:
| 字段 | 类型 | 说明 |
|---|---|---|
original |
string | 用户输入的原始项目描述 |
role_direction |
string | 目标岗位方向 |
star_version |
string | 改写后的 STAR 版本 |
quantify_tips |
string\[\] | 量化建议列表 |
keyword_swaps |
Record<string, string> | 关键词替换映射(原词→推荐词) |
improvement |
string | 整体优化说明 |
Record<string, string> 的使用 :keyword_swaps 使用 Record 类型,因为它需要存储键值对映射关系(原关键词 → 推荐关键词),这种结构天然适合字典类型的替换建议。
2.3 Service 层:业务逻辑设计
typescript
import { ResumeProjectData } from './简历项目经历改写Model'
export class ResumeProjectService {
private model: ResumeProjectData
constructor() {
this.model = new ResumeProjectData()
}
generateData(input: Record<string, Object>): ResumeProjectData {
let result: ResumeProjectData = new ResumeProjectData()
let original: string = input['original'] as string
let role: string = input['role_direction'] as string
let prompt: string = this.buildPrompt(original, role)
let response: string = this.callAI(prompt)
result = this.parseResponse(response, result)
return result
}
private buildPrompt(original: string, role: string): string {
return `你是一位资深简历优化专家,精通STAR法则...
原始描述:${original}
目标岗位:${role}
请输出 JSON 格式...`
}
}
2.4 Page 层:UI 组件设计
typescript
@Entry
@Component
struct ResumeProjectPage {
@State inputData: Record<string, Object> = {}
@State resultData: ResumeProjectData | null = null
@State showResult: boolean = false
private service: ResumeProjectService = new ResumeProjectService()
build() {
Column() {
Row() {
Text('← 返回').onClick(() => { router.back() })
Blank()
Text('简历项目改写')
Blank()
Text('')
}
Scroll() {
Column() {
Text('原内容')
TextInput({ placeholder: '请输入原内容' })
.onChange((val: string) => { this.inputData['original'] = val })
Text('岗位方向')
TextInput({ placeholder: '请输入岗位方向' })
.onChange((val: string) => { this.inputData['role_direction'] = val })
Button('AI 生成').onClick(() => {
this.resultData = this.service.generateData(this.inputData)
this.showResult = true
})
if (this.showResult && this.resultData !== null) {
Text('生成结果')
Text('项目改写')
}
}
}
}
}
}
三、AI 提示词工程原理
3.1 STAR 法则提示词设计
STAR 法则是简历写作中最核心的方法论,提示词需要精确指导 AI 按照 STAR 结构生成内容:
3.1.1 角色设定
你是一位资深简历优化专家,拥有10年以上的HR和职业咨询经验,曾为500强企业筛选过数万份简历,精通STAR法则在简历写作中的应用。
3.1.2 STAR 法则结构指导
请按照STAR法则重新组织项目经历:
S - Situation(情境):描述项目背景和面临的挑战
T - Task(任务):明确你的职责和任务目标
A - Action(行动):具体描述你采取的行动和使用的技术/方法
R - Result(结果):量化呈现项目成果和你的贡献
3.1.3 岗位关键词注入
目标岗位方向:{role_direction}
请根据该岗位的常见JD关键词,替换原始描述中不够专业的表达。
3.2 不同岗位方向的优化策略
| 岗位方向 | 关键词重点 | 量化指标示例 |
|---|---|---|
| 后端开发 | 高并发、微服务、性能优化 | QPS、响应时间、系统可用性 |
| 前端开发 | 用户体验、性能优化、组件化 | 加载时间、FCP、LCP |
| 数据分析 | 数据挖掘、A/B测试、可视化 | 准确率、提升率、覆盖率 |
| 产品经理 | 用户调研、需求分析、项目管理 | 用户增长、留存率、NPS |
3.3 完整 Prompt 示例
typescript
buildPrompt(original: string, role: string): string {
return `你是一位资深简历优化专家,擅长STAR法则简历写作。
请根据以下要求,对原始项目经历描述进行改写:
原始描述:
${original}
目标岗位方向:${role}
请严格按照STAR法则重新组织内容,并按照以下JSON格式输出:
{
"star_version": "按照STAR法则重新组织的项目经历描述,每个部分用S/T/A/R标记",
"quantify_tips": [
"建议1:将'提升了系统性能'改为'将系统响应时间从500ms降低到100ms,提升80%'",
"建议2:将'负责多个模块'改为'独立负责3个核心模块,覆盖用户量100万+'"
],
"keyword_swaps": {
"原词1": "推荐词1(带简要说明)",
"原词2": "推荐词2(带简要说明)"
},
"improvement": "整体优化说明,包括改写思路、重点改进方向等"
}
要求:
1. STAR版本必须包含完整的S/T/A/R四个部分
2. 量化建议至少2条,每条建议包含原表述和优化后的表述
3. 关键词替换至少3组,覆盖技术关键词和行业术语
4. 优化说明控制在200字以内,突出改写亮点
5. 保持专业、简洁、有力的语气`
}
3.4 响应解析
typescript
parseResponse(response: string, result: ResumeProjectData): ResumeProjectData {
try {
let parsed: Object = JSON.parse(response)
if (typeof parsed['star_version'] === 'string') {
result.star_version = parsed['star_version'] as string
}
if (Array.isArray(parsed['quantify_tips'])) {
result.quantify_tips = parsed['quantify_tips'] as string[]
}
if (typeof parsed['keyword_swaps'] === 'object') {
result.keyword_swaps = parsed['keyword_swaps'] as Record<string, string>
}
if (typeof parsed['improvement'] === 'string') {
result.improvement = parsed['improvement'] as string
}
} catch (e) {
result.star_version = '解析失败,请重试'
result.improvement = 'AI 服务暂时不可用'
}
return result
}
四、核心功能实现详解
4.1 输入区域实现
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['original'] = val })
// 岗位方向输入
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['role_direction'] = val })
4.2 结果展示区域
typescript
if (this.showResult && this.resultData !== null) {
// STAR 版本
Text('STAR 版本')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ top: 16, bottom: 8 })
Text(this.resultData.star_version)
.fontSize(14)
.fontColor($r('app.color.text_primary'))
.lineHeight(22)
.backgroundColor('#FFFFFF')
.padding(12)
.borderRadius(8)
.width('100%')
// 量化建议
Text('量化建议')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ top: 16, bottom: 8 })
ForEach(this.resultData.quantify_tips, (tip: string, index: number) => {
Row() {
Text(`${index + 1}.`)
.fontSize(14)
.fontColor('#3B82F6')
.margin({ right: 8 })
Text(tip)
.fontSize(14)
.fontColor($r('app.color.text_primary'))
}
.width('100%')
.margin({ bottom: 8 })
}, (tip: string, index: number) => index.toString())
// 关键词替换
Text('关键词替换')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ top: 16, bottom: 8 })
// 遍历 keyword_swaps 的键
let keys: string[] = Object.keys(this.resultData.keyword_swaps)
ForEach(keys, (key: string, index: number) => {
Row() {
Text(`${key} → `)
.fontSize(14)
.fontColor('#F59E0B')
.fontWeight(FontWeight.Bold)
Text(this.resultData.keyword_swaps[key])
.fontSize(14)
.fontColor('#22C55E')
}
.width('100%')
.margin({ bottom: 6 })
}, (key: string, index: number) => index.toString())
// 优化说明
Text('优化说明')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ top: 16, bottom: 8 })
Text(this.resultData.improvement)
.fontSize(14)
.fontColor($r('app.color.text_secondary'))
.backgroundColor('#FFFFFF')
.padding(12)
.borderRadius(8)
.width('100%')
}
4.3 完整数据流
用户输入:原始描述 = "负责开发了用户管理系统", 岗位方向 = "后端开发"
↓
inputData = { original: "负责开发了用户管理系统", role_direction: "后端开发" }
↓
点击 "AI 生成"
↓
service.generateData(inputData)
↓
构建 Prompt → 调用 AI → 解析响应
↓
返回 ResumeProjectData 实例
↓
resultData 更新 → showResult = true
↓
UI 渲染:STAR版本、量化建议、关键词替换、优化说明
五、用户体验优化
5.1 页面布局
┌──────────────────────────────────┐
│ ← 返回 简历项目改写 │
├──────────────────────────────────┤
│ 输入信息 │
│ ┌──────────────────────┐ │
│ │ 原内容 │ │
│ │ [负责开发了用户系统] │ │
│ │ 岗位方向 │ │
│ │ [后端开发] │ │
│ └──────────────────────┘ │
│ ┌──────────────────────┐ │
│ │ AI 生成 │ │
│ └──────────────────────┘ │
│ ┌──────────────────────┐ │
│ │ STAR 版本 │ │
│ │ S:公司用户量激增... │ │
│ │ T:负责用户系统架构...│ │
│ │ A:采用Spring Boot... │ │
│ │ R:系统响应时间降低...│ │
│ └──────────────────────┘ │
│ 量化建议 │
│ 1. 将'提升了性能'改为... │
│ 关键词替换 │
│ 负责 → 主导(体现主动性) │
│ 优化说明 │
│ 本次改写重点突出了... │
└──────────────────────────────────┘
5.2 交互优化
5.2.1 颜色编码
- 蓝色编号:量化建议序号
- 橙色:原关键词
- 绿色:推荐关键词
5.2.2 对比展示
原始描述和 STAR 版本并排或上下对比显示,让用户直观看到改写效果。
5.3 资源管理
typescript
.fontColor($r('app.color.text_primary'))
.fontColor($r('app.color.text_secondary'))
.backgroundColor('#F8FAFC')
.backgroundColor('#FFFFFF')
六、性能优化与最佳实践
6.1 ArkTS 约束适配
6.1.1 Object.keys 使用
typescript
// 正确:遍历 Record 的键
let keys: string[] = Object.keys(this.resultData.keyword_swaps)
ForEach(keys, (key: string, index: number) => {
Text(`${key} → ${this.resultData.keyword_swaps[key]}`)
}, (key: string, index: number) => index.toString())
6.1.2 类型断言安全
typescript
// 正确:使用 as 进行类型断言
let original: string = input['original'] as string
let role: string = input['role_direction'] as string
6.2 性能优化
6.2.1 条件渲染
typescript
if (this.showResult && this.resultData !== null) {
// 结果渲染
}
6.2.2 Object.keys 缓存
typescript
// 优化:缓存 Object.keys 结果
let keys: string[] = Object.keys(this.resultData.keyword_swaps)
// 在 ForEach 中使用缓存的 keys
6.3 错误处理
typescript
generateData(input: Record<string, Object>): ResumeProjectData {
try {
if (!input['original'] || !input['role_direction']) {
throw new Error('输入不完整')
}
// AI 调用
return this.parseResponse(this.callAI(this.buildPrompt(...)), new ResumeProjectData())
} catch (e) {
let result: ResumeProjectData = new ResumeProjectData()
result.improvement = '请确保输入内容完整后重试'
return result
}
}
6.4 代码组织
简历项目经历改写/
├── 简历项目经历改写Model.ets # 数据模型
├── 简历项目经历改写Service.ets # 业务逻辑
└── 简历项目经历改写Page.ets # 页面组件
七、总结与展望
7.1 项目成果
- 实现了基于 STAR 法则的简历项目经历 AI 改写
- 提供量化建议和关键词替换,提升简历专业性
- Model-Service-Page 架构确保代码清晰可维护
- 多维度结果展示,帮助用户学习简历写作技巧
7.2 技术经验
- STAR 法则的提示词设计需要精确的结构化指导
- Record 类型适合存储键值对映射数据
- 颜色编码和对比展示提升用户体验
7.3 未来展望
- 接入 JD 解析功能,自动提取岗位关键词
- 支持简历完整版生成(不仅仅是项目经历)
- 引入 ATS 系统兼容性检测
本文通过简历项目经历改写 AI 应用的完整开发实践,详细阐述了 HarmonyOS + ArkTS + AI 的技术栈应用。从 STAR 法则提示词工程到 ArkUI 多维度结果展示,全面展示了鸿蒙平台上智慧求职工具开发的全流程。