AI简历项目经历改写:基于HarmonyOS与ArkTS的AI原生应用开发全流程实践

摘要:本文以"AI简历项目经历改写"应用为完整案例,系统阐述基于HarmonyOS Next操作系统与ArkTS语言开发AI原生应用的完整技术实践。文章严格遵循六阶段开发方法论——对齐(Align)、架构(Architect)、原子化(Atomize)、审批(Approve)、自动化执行(Automate)、评估(Assess),从需求分析、架构设计、模块拆分、代码实现到质量控制,全方位呈现HarmonyOS生态下AI简历项目经历改写应用开发的技术要点与最佳实践。全文包含核心代码片段、架构决策分析、ArkTS语法约束详解及性能优化策略,为HarmonyOS应用开发者提供可参考的完整技术方案。


在这里插入图片描述

一、对齐阶段(Align):从模糊需求到精确规范

1.1 项目上下文分析

"AI简历项目经历改写"是运行在HarmonyOS Next系统上的AI原生应用,归属于一个包含多个 AI 应用的应用集合。该集合以"AI智能助手"为统一入口,覆盖健康生活、工作效率、创意娱乐、学习成长、职业发展六大领域,每个应用解决一个具体的用户场景问题。

1.1.1 技术栈全景

在开始编码之前,我们首先梳理了项目所涉及的技术栈,确保每个技术选型都经过充分考量:

技术维度 选型方案 版本/规格 选型理由
操作系统 HarmonyOS Next API 12+ 面向未来的全场景分布式OS
开发语言 ArkTS(基于TypeScript的鸿蒙原生语言) 原生支持,编译时类型安全
UI框架 ArkUI(声明式UI框架) 声明式范式,状态驱动渲染
路由方案 @kit.ArkUI router 系统内置 零额外依赖,原生性能
构建工具 Hvigor 官方构建工具,深度优化
包管理 oh-package.json5 标准鸿蒙包管理格式
1.1.2 现有代码模式分析

通过分析项目已有代码,我们识别出统一的架构模式——MVC变体(Model-View-Service),这是HarmonyOS社区中广泛采用的轻量级分层架构。每个应用由三个核心文件组成:

  1. *Page.ets:视图层,负责UI渲染和用户交互,以@Entry@Component装饰器标识。这是ArkUI声明式编程的核心载体,所有界面元素在此文件中定义。

  2. *Model.ets:数据模型层,定义数据结构,以export class导出。该层不包含任何业务逻辑,纯粹用于数据建模和类型约束。

  3. *Service.ets:业务逻辑层,封装数据生成和业务处理逻辑。该层是未来接入真实AI大模型API的扩展点。

这种模式在整个项目中被一致遵循,从"AI简历项目经历改写"到"AI求职信生成"、"AI品牌起名Slogan"等数十个应用,均采用相同的三文件结构。这种一致性极大地降低了维护成本和跨应用开发的认知负担。

Index.ets入口页面中,通过读取rawfile目录下的apps/apps.json配置文件动态加载应用列表,每个应用条目包含page字段指向对应的页面路径:

// Index.ets 中的动态加载逻辑
private loadApps(): void {
  try {
    let ctx: Context = getContext(this)
    let mgr = ctx.resourceManager
    let data: Uint8Array = mgr.getRawFileContentSync('apps/apps.json')
    let decoder: util.TextDecoder = util.TextDecoder.create('utf-8')
    let jsonStr: string = decoder.decodeToString(data)
    let rawList: AppJsonItem[] = JSON.parse(jsonStr) as AppJsonItem[]
    // ... 解析并构建AppInfo列表
  } catch {
    this.apps = this.getDefaultApps()
  }
}

这段代码展示了HarmonyOS资源管理的关键API:getRawFileContentSync用于读取rawfile目录下的二进制资源文件,TextDecoder用于将UTF-8编码的字节流解码为字符串。整个加载过程是同步的,适合在aboutToAppear生命周期钩子中执行。

1.1.3 应用启动流程分析

当用户从主页点击"AI简历项目经历改写"卡片时,完整的调用链如下:

用户点击卡片 → router.pushUrl({ url: app.pageUrl })
  → 系统加载AI简历项目经历改写 Page.ets
    → @Entry装饰器触发页面初始化
      → @Component构建组件树
        → @State变量初始化
          → build()方法执行UI渲染
            → 用户看到输入表单

这个流程体现了HarmonyOS声明式UI的核心思想:开发者只需描述UI的状态和结构,框架负责渲染和更新。

1.2 需求理解与确认

1.2.1 原始需求分析

项目经历改写是求职者简历优化中的核心环节。许多求职者拥有丰富的项目经验,但在简历中往往表述平淡、缺乏量化成果、无法突出个人贡献。一份优秀的项目经历描述需要遵循STAR原则(Situation-Task-Action-Result),突出量化成果,并针对目标岗位进行关键词优化。

AI简历项目经历改写应用的需求可以拆解为以下功能点:

  • F1:收集用户输入的项目经历原文
  • F2:收集用户的目标岗位信息
  • F3:基于STAR原则对项目经历进行结构化改写
  • F4:为改写结果添加量化指标(如提升百分比、覆盖人数等)
  • F5:提取项目经历中的亮点和关键词
  • F6:提供改写前后的对比展示
  • F7:给出简历改写技巧和建议
  • F8:支持多轮迭代优化
1.2.2 边界确认

经过需求澄清,我们确定了以下边界:

输入范围

  • 项目经历(必填):用户填写的原始项目经历描述
  • 目标岗位(必填):用户求职的目标岗位名称

输出范围

  • 改写后经历(rewritten):AI优化后的项目经历描述
  • STAR拆解(star_breakdown):按Situation/Task/Action/Result四个维度拆解
  • 量化指标列表(quantified):提取或生成的量化数据列表
  • 关键词列表(keywords_added):针对目标岗位新增的关键词
  • 亮点列表(highlights):从项目经历中提取的亮点
  • 改写前后对比(before/after):原始表述与优化后表述的对比
  • 改写技巧(tips):针对当前项目的优化建议

非功能需求

  • 页面响应时间:用户操作反馈应在100ms内
  • 数据生成时间:Mock数据生成应在50ms内完成
  • 支持API Level 12及以上设备
1.2.3 数据模型定义

基于上述分析,我们定义了如下数据模型:

// AI简历项目经历改写Model.ets
export class AI简历项目经历改写Data {
  rewritten: string = ''
  situation: string = ''
  task: string = ''
  action: string = ''
  result: string = ''
  star_breakdown: string = ''
  quantified: string[] = []
  metric: string = ''
  original: string = ''
  improved: string = ''
  keywords_added: string[] = []
  highlights: string[] = []
  before: string = ''
  after: string = ''
  before_after: string = ''
  tips: string = ''

  constructor() {
    this.rewritten = ''
    this.situation = ''
    this.task = ''
    this.action = ''
    this.result = ''
    this.star_breakdown = ''
    this.quantified = []
    this.metric = ''
    this.original = ''
    this.improved = ''
    this.keywords_added = []
    this.highlights = []
    this.before = ''
    this.after = ''
    this.before_after = ''
    this.tips = ''
  }
}

该模型涵盖了项目经历改写的全部输出维度。其中quantifiedkeywords_addedhighlights使用数组类型,便于通过ForEach指令在UI中循环渲染。

1.3 目标用户群体

  1. 应届毕业生:缺乏简历撰写经验,需要AI辅助优化项目经历描述
  2. 跳槽求职者:希望针对目标岗位精准优化简历,提升面试邀约率
  3. 职场人士:需要定期更新简历,但缺乏时间系统梳理项目经历
  4. 简历辅导师:作为辅助工具,提升简历优化服务的效率和质量

二、架构阶段(Architect):从系统架构到模块设计

2.1 整体架构设计

AI简历项目经历改写采用三层MVVM衍生架构,将数据模型、业务逻辑和UI展示进行清晰分离:

┌─────────────────────────────────────────────────────┐
│                    View 层                          │
│            AI简历项目经历改写Page.ets                │
│   @State 驱动数据绑定  |  ArkUI 声明式组件          │
│   TextInput  |  Button  |  Scroll  |  ForEach      │
└──────────────────────┬──────────────────────────────┘
                       │ 调用
┌──────────────────────▼──────────────────────────────┐
│                  Service 层                          │
│          AI简历项目经历改写Service.ets                │
│   数据生成逻辑  |  未来AI API调用封装               │
│   generateData(input) → AI简历项目经历改写Data       │
└──────────────────────┬──────────────────────────────┘
                       │ 实例化
┌──────────────────────▼──────────────────────────────┐
│                  Model 层                            │
│          AI简历项目经历改写Model.ets                  │
│   数据模型定义  |  类型约束  |  字段默认值           │
│   AI简历项目经历改写Data class                       │
└─────────────────────────────────────────────────────┘

各层职责说明:

  • Model层:纯数据模型,不含任何业务逻辑。所有字段使用默认值初始化,确保类型安全。
  • Service层:业务逻辑核心。当前使用Mock数据模拟AI生成结果,未来可替换为真实大模型API调用。该层是应用的"智能大脑"。
  • View层:纯UI展示。通过@State装饰器管理响应式数据,用户交互触发Service层调用,数据回流后自动更新UI。

2.2 核心数据流设计

数据流遵循单向数据流原则,确保数据变更可预测、可追踪:

用户输入 → @State inputData 变更 → 点击"生成"按钮
  → Service.generateData(inputData) 调用
    → 返回 AI简历项目经历改写Data 实例
      → @State resultData 赋值
        → showResult = true 触发条件渲染
          → UI 自动刷新展示结果

这个数据流的关键特点是:

  1. 单向流动:数据始终从用户输入流向Service层,再回流到View层,不存在双向绑定带来的副作用。
  2. 状态驱动:UI的更新完全由@State变量的变化驱动,开发者无需手动操作DOM。
  3. 声明式渲染:通过if条件语句控制结果区域的显示与隐藏,框架自动管理组件的创建和销毁。

2.3 View层组件树设计

页面组件树结构如下:

Column (根容器, backgroundColor: #EFF6FF)
├── Row (顶部导航栏)
│   ├── Text ("← 返回", 点击触发 router.back())
│   ├── Blank()
│   ├── Column (标题区)
│   │   ├── Text ("📱 AI简历项目经历改写")
│   │   └── Text ("RESUME · 简历卡片")
│   ├── Blank()
│   └── Text ("⭐")
├── Scroll (可滚动内容区, layoutWeight: 1)
│   └── Column
│       ├── Column (输入区)
│       │   ├── Text ("⭐ 项目经历", 标签)
│       │   ├── TextInput (项目经历输入框)
│       │   ├── Text ("⭐ 目标岗位", 标签)
│       │   └── TextInput (目标岗位输入框)
│       ├── Button ("📱 ⭐ 生成简历", 触发数据处理)
│       └── Column (结果展示区, 条件渲染)
│           ├── Text ("⭐ 简历卡片")
│           ├── Row (Rewritten)
│           ├── Row (Situation)
│           ├── Row (Task)
│           ├── Row (Action)
│           ├── Row (Result)
│           ├── Text ("Quantified") + ForEach
│           ├── Row (Metric)
│           ├── Row (Original)
│           ├── Row (Improved)
│           ├── Text ("Keywords added") + ForEach
│           ├── Text ("Highlights") + ForEach
│           ├── Row (Before)
│           ├── Row (After)
│           └── Row (Tips)

2.4 接口契约定义

Service层对外暴露的接口定义如下:

// 接口契约
interface IAI简历项目经历改写Service {
  /**
   * 生成简历项目经历改写数据
   * @param input - 用户输入数据,key为字段名,value为字段值
   * @returns AI简历项目经历改写Data - 完整的改写结果数据
   */
  generateData(input: Record<string, Object>): AI简历项目经历改写Data
}

该接口接受一个Record<string, Object>类型的输入参数,返回一个AI简历项目经历改写Data实例。Record类型是ArkTS支持的少数几个工具类型之一,用于表示键值对映射。

2.5 路由注册设计

在HarmonyOS中,每个页面都需要在路由配置中注册。通常,应用的页面路由注册在main_pages.json中完成:

{
  "src": [
    "pages/Index",
    "apps/AI简历项目经历改写/AI简历项目经历改写Page"
  ]
}

此外,在apps/apps.json配置文件中,需要添加对应的应用条目,以便主页能够识别并展示该应用:

{
  "apps": [
    {
      "appId": "ai-resume-experience-rewriter",
      "name": "AI简历项目经历改写",
      "page": "apps/AI简历项目经历改写/AI简历项目经历改写Page",
      "icon": "$media:ic_resume",
      "category": "职业发展",
      "description": "智能优化简历项目经历,突出量化成果"
    }
  ]
}

三、原子化阶段(Atomize):任务分解与模块实现

3.1 任务分解

将开发任务分解为以下可独立执行的原子任务:

任务ID 任务名称 依赖 预估工时 输出产物
T1 创建Model数据模型 0.5h AI简历项目经历改写Model.ets
T2 实现Service服务层 T1 1h AI简历项目经历改写Service.ets
T3 构建Page页面UI T1, T2 2h AI简历项目经历改写Page.ets
T4 注册路由配置 T3 0.5h main_pages.json
T5 集成到应用列表 T4 0.5h apps/apps.json
T6 编写单元测试 T2, T3 1h 测试用例

3.2 任务T1:创建Model数据模型

Model层是最基础的数据结构定义。在ArkTS中,类的定义需要遵循严格的语法约束:

// AI简历项目经历改写Model.ets
// 文件路径: entry/src/main/ets/apps/AI简历项目经历改写/AI简历项目经历改写Model.ets

export class AI简历项目经历改写Data {
  rewritten: string = ''
  situation: string = ''
  task: string = ''
  action: string = ''
  result: string = ''
  star_breakdown: string = ''
  quantified: string[] = []
  metric: string = ''
  original: string = ''
  improved: string = ''
  keywords_added: string[] = []
  highlights: string[] = ''
  before: string = ''
  after: string = ''
  before_after: string = ''
  tips: string = ''

  constructor() {
    this.rewritten = ''
    this.situation = ''
    this.task = ''
    this.action = ''
    this.result = ''
    this.star_breakdown = ''
    this.quantified = []
    this.metric = ''
    this.original = ''
    this.improved = ''
    this.keywords_added = []
    this.highlights = []
    this.before = ''
    this.after = ''
    this.before_after = ''
    this.tips = ''
  }
}

ArkTS语法要点分析:

  1. 字段声明必须在类内部:ArkTS不允许在构造函数中声明字段,所有字段必须在类声明内部直接声明并初始化。这是与标准TypeScript的重要区别。

  2. 显式类型标注:所有字段必须显式标注类型。ArkTS不支持anyunknown类型,因此必须使用具体的类型如stringstring[]等。

  3. 数组类型使用T[]语法:ArkTS支持T[]形式的数组类型标注,不支持索引签名。对于数组的访问,使用标准的索引语法。

  4. 构造函数中重复初始化:虽然字段在声明时已经初始化,但在构造函数中再次赋值是一种防御性编程实践,确保在对象创建时字段值被正确设置。

3.3 任务T2:实现Service服务层

Service层是业务逻辑的核心,负责数据生成和处理。当前阶段使用Mock数据模拟AI生成结果,未来可接入真实的大模型API:

// AI简历项目经历改写Service.ets
// 文件路径: 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 experienceVal: string = String(input['项目经历'] || '')

    result.rewritten = '生成结果:' + experienceVal
    result.star_breakdown = '生成结果:' + experienceVal
    result.quantified = ['示例数据1', '示例数据2', '示例数据3']
    result.keywords_added = ['示例项1', '示例项2', '示例项3']
    result.highlights = ['示例项1', '示例项2', '示例项3']
    result.before_after = '生成结果:' + experienceVal
    result.tips = '生成结果:' + experienceVal
    return result
  }
}

设计要点分析:

  1. 依赖注入准备:Service类通过构造函数持有Model实例,这种设计为未来替换为真实AI API调用提供了清晰的扩展点。

  2. 输入参数设计:使用Record<string, Object>作为输入参数类型,这是一种灵活的设计,允许未来扩展更多输入字段而不需要修改接口签名。Record是ArkTS支持的少数几个工具类型之一。

  3. Mock数据策略:当前实现使用拼接字符串和示例数组作为Mock数据,确保UI开发阶段可以正常展示和调试。未来接入真实AI API时,只需修改generateData方法的实现,不需要修改Page层代码。

  4. 类型安全转换:使用String()函数将Object类型安全地转换为string,避免类型错误。

3.4 任务T3:构建Page页面UI

Page层是面向用户的UI界面,采用ArkUI声明式语法构建。以下是完整的页面实现:

// AI简历项目经历改写Page.ets
// 文件路径: 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() {
      // 顶部导航栏
      Row() {
        Text('← 返回')
          .fontSize(13)
          .fontColor('#1E40AF')
          .onClick(() => {
            router.back()
          })
        Blank()
        Column() {
          Text('📱 AI简历项目经历改写')
            .fontSize(17)
            .fontWeight(FontWeight.Bold)
            .fontColor('#1E3A5F')
          Text('RESUME · 简历卡片')
            .fontSize(9)
            .fontColor('#3B82F6')
            .margin({ top: 2 })
        }
        Blank()
        Text('⭐')
          .fontSize(22)
      }
      .width('100%')
      .padding({ left: 20, right: 20, top: 16, bottom: 14 })
      .backgroundColor('#EFF6FF')

      // 可滚动内容区
      Scroll() {
        Column() {
          // 输入卡片
          Column() {
            Text('⭐ 项目经历')
              .fontSize(11)
              .fontColor('#1E3A5F')
              .margin({ top: 6, bottom: 3 })
            TextInput({ placeholder: '请输入项目经历' })
              .fontSize(13)
              .height(40)
              .backgroundColor('#FFFFFF')
              .borderRadius(6)
              .border({ width: 1, color: '#93C5FD' })
              .padding({ left: 12, right: 12 })
              .onChange((val: string) => {
                this.inputData['项目经历'] = val
              })

            Text('⭐ 目标岗位')
              .fontSize(11)
              .fontColor('#1E3A5F')
              .margin({ top: 6, bottom: 3 })
            TextInput({ placeholder: '请输入目标岗位' })
              .fontSize(13)
              .height(40)
              .backgroundColor('#FFFFFF')
              .borderRadius(6)
              .border({ width: 1, color: '#93C5FD' })
              .padding({ left: 12, right: 12 })
              .onChange((val: string) => {
                this.inputData['目标岗位'] = val
              })
          }
          .width('100%')
          .padding(18)
          .backgroundColor('#FFFFFF')
          .borderRadius(6)
          .border({ width: 1, color: '#BFDBFE' })
          .margin({ top: 6 })

          // 生成按钮
          Button('📱 ⭐ 生成简历')
            .width('100%')
            .height(50)
            .backgroundColor('#1D4ED8')
            .borderRadius(6)
            .fontColor('#FFFFFF')
            .fontSize(16)
            .fontWeight(FontWeight.Bold)
            .margin({ top: 18, bottom: 14 })
            .onClick(() => {
              this.resultData = this.service.generateData(this.inputData)
              this.showResult = true
            })

          // 结果展示区(条件渲染)
          if (this.showResult && this.resultData !== null) {
            Column() {
              Text('⭐ 简历卡片')
                .fontSize(15)
                .fontWeight(FontWeight.Bold)
                .fontColor('#1E3A5F')
                .margin({ bottom: 12 })

              // 逐行展示结果字段
              Row() {
                Text('Rewritten: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.rewritten)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Situation: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.situation)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Task: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.task)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Action: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.action)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Result: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.result)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              // 量化指标列表
              Text('Quantified')
                .fontSize(13)
                .fontWeight(FontWeight.Bold)
                .fontColor('#333333')
                .margin({ top: 10, bottom: 6 })

              if (this.resultData.quantified) {
                ForEach(this.resultData.quantified,
                  (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()
                )
              }

              Row() {
                Text('Metric: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.metric)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Original: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.original)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Improved: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.improved)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              // 关键词列表
              Text('Keywords added')
                .fontSize(13)
                .fontWeight(FontWeight.Bold)
                .fontColor('#333333')
                .margin({ top: 10, bottom: 6 })

              if (this.resultData.keywords_added) {
                ForEach(this.resultData.keywords_added,
                  (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()
                )
              }

              // 亮点列表
              Text('Highlights')
                .fontSize(13)
                .fontWeight(FontWeight.Bold)
                .fontColor('#333333')
                .margin({ top: 10, bottom: 6 })

              if (this.resultData.highlights) {
                ForEach(this.resultData.highlights,
                  (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()
                )
              }

              Row() {
                Text('Before: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.before)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('After: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.after)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })

              Row() {
                Text('Tips: ')
                  .fontSize(12)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#666666')
                Text(this.resultData.tips)
                  .fontSize(12)
                  .fontColor('#333333')
              }
              .width('100%')
              .padding({ top: 4, bottom: 4 })
          
Logo

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

更多推荐