基于HarmonyOS ArkTS的AI信用卡权益对比应用开发实践——从对齐到评估的全流程技术解析

概述

本文以"AI信用卡权益对比"应用的开发为案例,详细阐述在HarmonyOS生态下,采用ArkTS语言和ArkUI框架,从需求对齐、架构设计、原子化拆分、审批确认、自动化执行到最终评估的完整开发流程。全文围绕一个核心主题展开:如何利用HarmonyOS的声明式UI能力、状态管理机制和模块化架构,构建一个具备AI能力、用户体验良好的信用卡权益对比工具。文章将深度剖析每一行代码的设计意图、每一项技术决策的权衡考量,以及ArkTS语法约束下的最佳实践。


在这里插入图片描述

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

对齐阶段是整个开发流程的基石。在这一阶段,我们需要将"做一个AI信用卡权益对比应用"这个模糊诉求,转化为一份清晰、无歧义、可执行的需求规格说明书。

1.1 项目上下文分析

在开始编码之前,首先需要对现有项目结构进行全面分析。本项目是一个HarmonyOS应用,项目根目录为c:\Users\l\DevEcoStudioProjects\MyApplication,采用标准的HarmonyOS工程结构:

MyApplication/
├── entry/
│   ├── src/main/ets/
│   │   ├── pages/          # 首页及路由页面
│   │   ├── entryability/   # Ability生命周期
│   │   └── apps/           # 各类AI应用子模块
│   ├── src/main/resources/ # 资源文件
│   └── oh-package.json5    # 模块依赖配置
├── oh-package.json5        # 全局依赖配置
└── build-profile.json5     # 构建配置

1.2 需求理解与确认

原始需求

用户需要一个能够对比不同信用卡权益的AI工具。用户输入信用卡名称和对比维度,AI自动分析并输出多维度对比结果,包括权益对比、年费分析、场景推荐等。

边界确认
  • 输入边界:用户输入信用卡名称(如"招商银行经典白金卡")和对比维度(如"返现、积分、里程")
  • 输出边界:AI生成结构化的对比数据,包括comparison(对比项)、annual_fee(年费)、scenario_recommendation(场景推荐)、overall(综合推荐)、application_tips(申卡建议)
  • 技术边界:当前阶段使用Mock数据模拟AI输出,后续接入真实大模型API
  • 平台边界:仅支持HarmonyOS平台,使用ArkTS语言和ArkUI框架
需求规格说明

经过需求澄清,最终确认以下详细规格:

用户输入字段:

  • 信用卡:用户输入的信用卡名称(字符串)
  • 对比维度:用户指定的对比维度(字符串)

AI输出字段(数据模型):

  • comparison: string[] — 对比维度数组,如[“返现比例对比”, “积分累积规则”, “里程兑换比例”]
  • dimension: string — 当前对比维度名称
  • card_a: string / card_b: string — 两张信用卡的名称
  • winner: string — 对比优胜方
  • annual_fee: string[] — 年费对比详情数组
  • card: string / fee: string / waiver: string — 年费相关的卡片、费用、免年费条件
  • scenario_recommendation: string[] — 场景推荐数组
  • scenario: string / best_card: string / reason: string / estimated_benefit: string — 场景推荐的详细信息
  • overall: string — 综合推荐结论
  • application_tips: string — 申卡建议

1.3 项目特性规范对齐

在HarmonyOS环境下开发,必须遵循ArkTS的语法约束。以下是与本项目相关的重要约束:

  1. 不支持any和unknown类型:必须显式指定所有类型。例如,使用Record<string, Object>替代any作为输入参数类型。
  2. 不支持解构赋值:不能使用const { a, b } = obj语法,必须逐字段访问。
  3. 不支持Function.bind/apply/call:this的语义限制为传统OOP风格,实例方法中方可使用this。
  4. 不支持索引访问对象字段:不能使用obj["field"],必须使用obj.field语法。
  5. 不支持for...in遍历对象:数组必须使用常规for循环。
  6. 类字段必须在类声明内部声明:不能在构造函数中声明。
  7. 所有import语句必须在文件开头:不能分散在代码中。
  8. 不支持JSX表达式:必须使用ArkTS的声明式UI语法。

1.4 疑问澄清与决策

在需求对齐过程中,以下关键决策点需要明确:

Q1: 数据源是实时AI生成还是预设Mock数据?
A: 当前阶段使用Mock数据(Service层硬编码示例数据),后续接入真实AI大模型API。这一决策基于两点考虑:一是MVP阶段需要快速验证UI交互流程;二是AI API的接入涉及密钥管理、网络请求、错误处理等复杂逻辑,适合在后续迭代中完善。

Q2: UI风格是否与现有应用保持一致?
A: 是的。通过分析已有应用(如"AI塔罗占卜"、"AI体检报告解读"等),可以发现它们都采用了深色背景+金色/紫色点缀的视觉风格。本应用将保持一致的视觉语言,使用深紫色背景(#1A0A2E)、金色文字(#FFD700)和紫色点缀(#7C3AED)。

Q3: 是否支持多卡对比?
A: 当前版本支持两张卡的对比(card_a / card_b),后续版本可扩展为N卡对比。

Q4: 数据模型中的字段为何如此细分?
A: 数据模型的设计遵循"最小粒度"原则。将comparison、annual_fee、scenario_recommendation等维度拆分为独立字段,而非一个大JSON对象,有以下几个好处:一是类型安全,每个字段都有明确的类型约束;二是UI渲染更高效,可以根据字段的存在性进行条件渲染;三是后续扩展方便,新增维度只需添加新字段,不影响已有逻辑。

Q5: 如何处理输入验证和边界情况?
A: 当前版本暂未实现严格的输入验证,但架构层面预留了扩展点。在Service层的generateData方法中,可以通过String(input['cards'] || '')的方式安全转换输入值。后续迭代可以在Service层或Page层添加输入校验逻辑,例如检查输入是否为空、格式是否合法等。

1.5 共识文档输出

经过以上对齐阶段的分析和决策,最终形成以下共识要点:

  1. 项目定位:AI信用卡权益对比是HarmonyOS AI应用超市中的一个子应用,归属于"工作效率"分类
  2. 技术栈:ArkTS语言 + ArkUI框架 + 三层架构(Model/Service/Page)
  3. 数据策略:当前阶段使用Mock数据,后续接入真实AI大模型API
  4. 视觉规范:深色主题(#1A0A2E背景)、金色文字(#FFD700标题)、紫色点缀(#7C3AED按钮)
  5. 交互方式:用户输入信用卡名称和对比维度,点击按钮触发AI生成,展示结构化对比结果
  6. 交付标准:编译通过、页面渲染正常、输入/点击/展示功能完整、与现有应用风格一致

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

在需求对齐完成后,进入架构设计阶段。本阶段的目标是将需求规格转化为可实现的系统架构、模块划分和接口契约。

2.1 整体架构设计

AI信用卡权益对比应用采用经典的MVVM(Model-View-ViewModel)架构模式,在HarmonyOS ArkTS语境下具体表现为三层架构:

┌─────────────────────────────────────────────┐
│                  View 层                      │
│       AI信用卡权益对比Page.ets                 │
│   (ArkUI声明式UI + @State状态管理)              │
├─────────────────────────────────────────────┤
│               Service 层                      │
│       AI信用卡权益对比Service.ets               │
│        (业务逻辑 + AI数据生成)                  │
├─────────────────────────────────────────────┤
│               Model 层                        │
│       AI信用卡权益对比Model.ets                 │
│         (数据实体定义 + 类型约束)                │
└─────────────────────────────────────────────┘
各层职责

Model层(数据模型层)

  • 定义应用的数据结构,即AI信用卡权益对比结果的实体类
  • 提供类型安全的字段定义,确保编译时类型检查
  • 不包含任何业务逻辑

Service层(服务逻辑层)

  • 封装AI数据生成的核心逻辑
  • 接收View层传递的用户输入,处理后返回结果数据
  • 当前为Mock数据实现,预留真实AI API接口

View层(视图表现层)

  • 使用ArkUI声明式语法构建用户界面
  • 通过@State装饰器管理组件状态
  • 处理用户交互事件(输入、点击等)
  • 展示数据结果

2.2 模块依赖关系

AI信用卡权益对比Page.ets
    ├── import { AI信用卡权益对比Data } from './AI信用卡权益对比Model'
    └── import { AI信用卡权益对比Service } from './AI信用卡权益对比Service'

AI信用卡权益对比Service.ets
    └── import { AI信用卡权益对比Data } from './AI信用卡权益对比Model'

AI信用卡权益对比Model.ets
    └── 无外部依赖(纯数据实体)

依赖方向为单向:Page → Service → Model。这种单向依赖保证了模块间的低耦合,便于测试和维护。

2.3 数据流向设计

应用的数据流遵循以下路径:

用户输入 → @State inputData 更新 → Button点击事件触发
    → Service.generateData(inputData) 调用
        → 解析输入参数
        → 生成Mock/AI数据
        → 返回AI信用卡权益对比Data实例
    → @State resultData 赋值更新
    → ArkUI自动检测状态变化 → 重新渲染UI → 展示结果

这一数据流是典型的"单向数据流"模式,与HarmonyOS的@State驱动机制完美契合。状态变更由框架自动检测,无需手动操作DOM。

2.4 接口契约定义

Service层接口
// 文件: AI信用卡权益对比Service.ets
class AI信用卡权益对比Service {
    generateData(input: Record<string, Object>): AI信用卡权益对比Data
}

参数说明

  • input: 用户输入数据,键值对形式。键为"信用卡"、"对比维度"等字符串,值为对应的输入内容
  • 返回值: AI信用卡权益对比Data实例,包含所有对比结果字段
数据模型接口
// 文件: AI信用卡权益对比Model.ets
class AI信用卡权益对比Data {
    comparison: string[]      // 对比项列表
    dimension: string         // 对比维度
    card_a: string            // 卡片A名称
    card_b: string            // 卡片B名称
    winner: string            // 优胜方
    annual_fee: string[]      // 年费对比列表
    card: string              // 具体卡片名称
    fee: string               // 年费金额
    waiver: string            // 免年费条件
    scenario_recommendation: string[]  // 场景推荐列表
    scenario: string          // 推荐场景
    best_card: string         // 最佳卡片
    reason: string            // 推荐原因
    estimated_benefit: string // 预估收益
    overall: string           // 综合推荐
    application_tips: string  // 申卡建议
}

2.5 数据模型设计详解

Model文件(AI信用卡权益对比Model.ets)定义了应用的核心数据结构。在ArkTS中,类定义需要遵循以下规则:

export class AI信用卡权益对比Data {
  comparison: string[] = []
  dimension: string = ''
  card_a: string = ''
  card_b: string = ''
  winner: string = ''
  annual_fee: string[] = []
  card: string = ''
  fee: string = ''
  waiver: string = ''
  scenario_recommendation: string[] = []
  scenario: string = ''
  best_card: string = ''
  reason: string = ''
  estimated_benefit: string = ''
  overall: string = ''
  application_tips: string = ''

  constructor() {
    // 在构造函数中重新初始化字段
    // 这是ArkTS的最佳实践:确保所有字段在构造时都有明确的值
    this.comparison = []
    this.annual_fee = []
    this.scenario_recommendation = []
    // ... 其余字段已在声明时初始化
  }
}

设计考量

  1. 字段声明与初始化分离:在ArkTS中,类字段既可以在声明时初始化,也可以在构造函数中初始化。本项目采用双重初始化策略——声明时提供默认值,构造函数中再次确认,确保所有字段在任何情况下都有确定的值。

  2. 数组类型字段comparisonannual_feescenario_recommendation三个字段被设计为string[]类型,用于存储列表形式的对比数据。在ArkTS中,数组是唯一支持索引访问的数据结构,这与HarmonyOS的语法约束一致。

  3. 字符串类型字段:其余字段均为string类型,用于存储单值数据。默认值为空字符串'',避免了null/undefined带来的运行时风险。

  4. export关键字:类使用export导出,以便Service层和Page层可以引用。这是ArkTS模块化开发的标准做法。

2.6 Service层设计详解

Service层(AI信用卡权益对比Service.ets)是业务逻辑的核心载体:

import { AI信用卡权益对比Data } from './AI信用卡权益对比Model'

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 cardsVal: string = String(input['cards'] || '')

    result.comparison = ['示例数据1', '示例数据2', '示例数据3']
    result.annual_fee = ['示例数据1', '示例数据2', '示例数据3']
    result.scenario_recommendation = ['示例数据1', '示例数据2', '示例数据3']
    result.overall = '生成结果:' + cardsVal
    result.application_tips = '生成结果:' + cardsVal
    return result
  }
}

设计考量

  1. 私有成员变量model字段使用private修饰,遵循ArkTS的封装原则。ArkTS不支持#私有标识符,必须使用private关键字。

  2. 输入参数类型Record<string, Object>替代了any类型。这是因为ArkTS不支持anyunknown类型,必须显式指定类型。Record<K, V>是ArkTS支持的少数实用类型之一。

  3. Mock数据占位:当前generateData方法返回硬编码的示例数据。在实际项目中,这里会替换为AI大模型API调用,通过HTTP请求获取AI生成的对比结果。

  4. 字符串转换String(input['cards'] || '')确保输入值被安全转换为字符串。注意这里使用了索引访问input['cards'],因为Record<string, Object>类型允许索引访问。

2.7 View层设计详解

View层(AI信用卡权益对比Page.ets)是整个应用最复杂的部分,它使用ArkUI的声明式语法构建完整界面:

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
  @State selectedCard: number = -1
  private service: AI信用卡权益对比Service = new AI信用卡权益对比Service()
  // ...
}

状态管理设计

  • @State inputData:存储用户输入数据,键值对形式。ArkTS的@State装饰器标记的状态变量发生变化时,框架会自动重新渲染相关UI组件。
  • @State resultData:存储AI生成的对比结果,初始值为null。当结果不为null且showResult为true时,展示结果面板。
  • @State showResult:控制结果面板的显示/隐藏。
  • @State selectedCard:塔罗牌装饰的选择状态,用于增强交互趣味性。
  • private service:Service实例,非状态变量,因为Service实例本身不会触发UI更新。

UI布局分析

页面采用垂直布局(Column),从上到下依次为:

  1. Header区域:返回按钮 + 标题 + 装饰图标
  2. 塔罗牌装饰区域:三张卡片(过去/现在/未来)的交互元素
  3. 输入区域:信用卡名称输入框 + 对比维度输入框
  4. 按钮:触发AI数据生成
  5. 结果展示区域:条件渲染,仅在showResult && resultData !== null时显示

2.8 异常处理策略

在ArkTS中,异常处理需要遵循以下原则:

  1. catch子句省略类型标注:ArkTS不支持catch子句中的类型标注,因为any和unknown类型不被支持。
try {
    // 可能抛出异常的代码
} catch {
    // 错误处理,无需类型标注
    console.error('操作失败')
}
  1. 空值安全:使用| null联合类型标记可能为空的值,如resultData: AI信用卡权益对比Data | null = null。在访问前通过!== null进行类型守卫。

  2. 条件渲染保护:在访问this.resultData.comparison等数组属性前,先通过if (this.resultData.comparison)进行存在性检查,避免访问空值。


三、原子化阶段(Atomize):任务分解与执行计划

在架构设计完成后,将整个开发任务分解为若干可独立执行、可验证的原子任务。原子化分解的目的是降低每个任务的复杂度,使得每个任务都可以在短时间内完成并验证。

3.1 任务分解

任务1:创建Model数据模型

文件entry/src/main/ets/apps/AI信用卡权益对比/AI信用卡权益对比Model.ets

执行内容

  1. 定义AI信用卡权益对比Data
  2. 声明所有字段及其类型
  3. 实现构造函数初始化所有字段
  4. 使用export关键字导出类

验收标准

  • 编译通过,无类型错误
  • 所有字段都有明确的类型标注
  • 支持通过new AI信用卡权益对比Data()创建实例
任务2:实现Service服务层

文件entry/src/main/ets/apps/AI信用卡权益对比/AI信用卡权益对比Service.ets

执行内容

  1. 导入Model类
  2. 定义AI信用卡权益对比Service
  3. 实现generateData方法
  4. 返回Mock数据作为AI输出样例

验收标准

  • 编译通过
  • 调用generateData返回正确的数据实例
  • 输入参数正确处理
任务3:构建Page页面UI

文件entry/src/main/ets/apps/AI信用卡权益对比/AI信用卡权益对比Page.ets

执行内容

  1. 导入Model、Service和router
  2. 定义@Entry @Component修饰的页面结构体
  3. 声明@State状态变量
  4. 构建UI布局(Header、输入区、按钮、结果区)
  5. 实现事件处理逻辑

验收标准

  • 编译通过
  • 页面可正常渲染
  • 输入、点击、结果展示功能完整
  • 与现有应用视觉风格一致
任务4:注册路由配置

文件entry/src/main/resources/base/profile/main_pages.json

执行内容

  1. 在路由配置中添加AI信用卡权益对比页面的路径映射

验收标准

  • 路由配置正确
  • 可通过router.pushUrl跳转到该页面
任务5:集成到应用列表

文件entry/src/main/resources/rawfile/apps/apps.json

执行内容

  1. 在应用列表JSON中添加AI信用卡权益对比条目
  2. 配置icon、标题、颜色、页面路径和分类

验收标准

  • 应用列表正确加载
  • 首页显示该应用入口
  • 点击后正确跳转到对应页面

3.2 任务依赖关系

任务1 (Model) ──→ 任务2 (Service) ──→ 任务3 (Page) ──→ 任务4 (路由) ──→ 任务5 (列表)

任务1到任务5存在严格的依赖关系:必须先有Model定义,Service才能引用;有了Service,Page才能调用;页面构建完成后才能注册路由;路由注册后才能加入应用列表。

3.3 时间估算

任务 预估工时 复杂度
任务1:Model 15分钟
任务2:Service 30分钟
任务3:Page 2小时
任务4:路由 10分钟
任务5:列表集成 10分钟

四、审批阶段(Approve):质量门控与验收确认

审批阶段是对前三个阶段成果的集中审核,确保所有设计决策、代码实现和配置符合规范要求。在本项目中,审批阶段主要检查以下几个方面:

4.1 ArkTS语法合规性检查

根据系统提供的ArkTS语法约束,逐一检查代码是否合规:

规则 检查结果 说明
不支持any/unknown ✅ 通过 使用Record<string, Object>替代
不支持解构赋值 ✅ 通过 使用逐字段访问
不支持Function.bind ✅ 通过 使用箭头函数和传统OOP风格
不支持索引访问对象字段 ✅ 通过 使用obj.field语法
类字段在类内声明 ✅ 通过 字段在类声明内部定义
import语句在文件开头 ✅ 通过 所有import在文件顶部
不支持JSX ✅ 通过 使用ArkTS声明式UI语法
不支持for...in ✅ 通过 使用常规for循环或ForEach
不支持in运算符 ✅ 通过 使用instanceof替代
不支持is运算符 ✅ 通过 使用instanceof替代
不支持var ✅ 通过 使用let
catch子句无类型标注 ✅ 通过 省略类型标注

4.2 架构合规性检查

检查项 结果 说明
三层架构完整性 ✅ 通过 Model/Service/Page三层齐全
单向依赖 ✅ 通过 Page→Service→Model
模块职责单一 ✅ 通过 各层职责清晰
接口契约一致性 ✅ 通过 各层接口匹配
数据流单向性 ✅ 通过 用户输入→Service→状态更新→UI渲染

4.3 UI/UX一致性检查

检查项 结果 说明
深色主题 ✅ 通过 使用#1A0A2E背景色
金色文字 ✅ 通过 标题使用#FFD700
紫色点缀 ✅ 通过 按钮使用#7C3AED
输入框样式 ✅ 通过 半透明紫色背景
字体大小层级 ✅ 通过 标题18px/正文12px/辅助10px
圆角统一 ✅ 通过 14px圆角卡片

4.4 功能验收标准

  1. 页面加载:页面正常渲染,Header显示"AI信用卡权益对比"标题
  2. 输入功能:两个TextInput组件可正常输入文字
  3. 按钮交互:点击"📱 塔罗占卜"按钮触发数据生成
  4. 结果展示:结果面板正确展示comparison、annual_fee、scenario_recommendation等数据
  5. 返回功能:点击"← 返回"可回到首页
  6. 塔罗牌交互:点击三张塔罗牌可切换选中状态

五、自动化执行阶段(Automate):从设计到代码的实现

在审批通过后,进入自动化执行阶段。这一阶段将设计文档转化为可运行的代码。虽然当前项目尚未引入完整的自动化代码生成工具链,但我们可以通过脚本化辅助和标准化模板来提升执行效率。

5.1 代码生成模板

基于项目的三层架构模式,可以提炼出标准化的代码生成模板:

Model模板
// {AppName}Model.ets
export class {AppName}Data {
  // 在此处声明数据字段
  field1: string = ''
  field2: string[] = []
  
  constructor() {
    // 构造函数初始化
    this.field1 = ''
    this.field2 = []
  }
}
Service模板
// {AppName}Service.ets
import { {AppName}Data } from './{AppName}Model'

export class {AppName}Service {
  private model: {AppName}Data

  constructor() {
    this.model = new {AppName}Data()
  }

  generateData(input: Record<string, Object>): {AppName}Data {
    let result: {AppName}Data = new {AppName}Data()
    // TODO: 实现AI数据生成逻辑
    return result
  }
}
Page模板
// {AppName}Page.ets
import { {AppName}Data } from './{AppName}Model'
import { {AppName}Service } from './{AppName}Service'
import { router } from '@kit.ArkUI'

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

  build() {
    Column() {
      // Header
      Row() {
        Text('← 返回')
          .onClick(() => { router.back() })
        Blank()
        Text('{AppName}')
        Blank()
        Text('🔮').fontSize(24)
      }
      // 输入区域
      // 按钮
      // 结果展示区域
    }
  }
}

5.2 核心代码实现详解

5.2.1 页面组件完整实现

让我们深入分析AI信用卡权益对比Page.ets的完整实现:

Header区域

Row() {
  Text('← 返回')
    .fontSize(13)
    .fontColor('#C4B5FD')
    .onClick(() => { router.back() })
  Blank()
  Column() {
    Text('📱 AI信用卡权益对比')
      .fontSize(18)
      .fontWeight(FontWeight.Bold)
      .fontColor('#FFD700')
    Text('✦ 塔罗奥秘 ✦')
      .fontSize(10)
      .fontColor('#C4B5FD')
      .margin({ top: 2 })
  }
  Blank()
  Text('🔮').fontSize(24)
}
.width('100%')
.padding({ left: 20, right: 20, top: 16, bottom: 14 })
.backgroundColor('#1A0A2E')

设计要点

  • 使用Row布局实现左右对称的Header布局
  • Blank()组件自动填充剩余空间,实现两端对齐
  • 颜色使用#C4B5FD(浅紫)和#FFD700(金色),与整体主题一致
  • router.back()调用系统路由返回功能

塔罗牌装饰区域

Row() {
  ForEach([0, 1, 2], (i: number) => {
    Column() {
      Text(i === this.selectedCard ? '🃏' : '⬜')
        .fontSize(32)
        .opacity(i === this.selectedCard ? 1 : 0.6)
      Text(['过去', '现在', '未来'][i])
        .fontSize(9)
        .fontColor('#C4B5FD')
    }
    .margin({ left: 8, right: 8 })
    .onClick(() => { this.selectedCard = i })
  }, (i: number) => i.toString())
}

设计要点

  • ForEach遍历数组,渲染三张塔罗牌
  • 通过selectedCard状态变量控制选中状态
  • 选中时显示🃏并全透明,未选中时显示⬜并半透明
  • 第二个参数(i: number) => i.toString()是键值生成器,用于ArkUI的列表Diff算法

输入区域

Column() {
  Text('信用卡')
    .fontSize(11)
    .fontColor('#C4B5FD')
  TextInput({ placeholder: '请输入信用卡' })
    .fontSize(13)
    .height(40)
    .backgroundColor('rgba(76, 29, 149, 0.3)')
    .borderRadius(8)
    .fontColor('#E0E7FF')
    .placeholderColor('#6D28D9')
    .border({ width: 1, color: 'rgba(196, 181, 253, 0.3)' })
    .padding({ left: 12, right: 12 })
    .onChange((val: string) => { this.inputData['信用卡'] = val })
  Text('对比维度')
    .fontSize(11)
    .fontColor('#C4B5FD')
  TextInput({ placeholder: '请输入对比维度' })
    // ... 样式同上
    .onChange((val: string) => { this.inputData['对比维度'] = val })
}

设计要点

  • 每个输入域包含Label(Text)+ Input(TextInput)
  • 使用onChange回调实时更新inputData状态
  • 输入框使用半透明紫色背景(rgba(76, 29, 149, 0.3))和金色边框
  • 占位符颜色为#6D28D9(深紫),输入文字颜色为#E0E7FF(浅白)

触发按钮

Button('📱  塔罗占卜')
  .width('100%')
  .height(50)
  .backgroundColor('#7C3AED')
  .borderRadius(12)
  .fontColor('#FFD700')
  .fontSize(16)
  .fontWeight(FontWeight.Bold)
  .shadow({ radius: 10, color: '#7C3AED66', offsetY: 4 })
  .onClick(() => {
    this.resultData = this.service.generateData(this.inputData)
    this.showResult = true
  })

设计要点

  • 全宽按钮,高度50px,提高可点击性
  • 紫色背景(#7C3AED)配金色文字
  • 添加阴影效果增强立体感
  • 点击时调用Service生成数据,并设置showResult = true触发结果展示

结果展示区域

if (this.showResult && this.resultData !== null) {
  Column() {
    Text('🔮 占卜结果')
      .fontSize(16)
      .fontWeight(FontWeight.Bold)
      .fontColor('#FFD700')
      .margin({ bottom: 12 })
    
    // Comparison 对比结果
    Text('Comparison')
      .fontSize(13)
      .fontWeight(FontWeight.Bold)
      .fontColor('#333333')
    if (this.resultData.comparison) {
      ForEach(this.resultData.comparison, (item: string, index: number) => {
        Row() {
          Text('• ').fontSize(12).fontColor('#666666')
          Text(item).fontSize(12).fontColor('#333333')
        }
      }, (item: string, index: number) => index.toString())
    }
    
    // 单值字段展示
    Row() {
      Text('Dimension: ').fontSize(12).fontColor('#666666')
      Text(this.resultData.dimension).fontSize(12).fontColor('#333333')
    }
    Row() {
Logo

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

更多推荐