基于HarmonyOS ArkTS的AI信用卡权益对比应用开发实践——从对齐到评估的全流程技术解析
基于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的语法约束。以下是与本项目相关的重要约束:
- 不支持any和unknown类型:必须显式指定所有类型。例如,使用
Record<string, Object>替代any作为输入参数类型。 - 不支持解构赋值:不能使用
const { a, b } = obj语法,必须逐字段访问。 - 不支持Function.bind/apply/call:this的语义限制为传统OOP风格,实例方法中方可使用this。
- 不支持索引访问对象字段:不能使用
obj["field"],必须使用obj.field语法。 - 不支持
for...in遍历对象:数组必须使用常规for循环。 - 类字段必须在类声明内部声明:不能在构造函数中声明。
- 所有import语句必须在文件开头:不能分散在代码中。
- 不支持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 共识文档输出
经过以上对齐阶段的分析和决策,最终形成以下共识要点:
- 项目定位:AI信用卡权益对比是HarmonyOS AI应用超市中的一个子应用,归属于"工作效率"分类
- 技术栈:ArkTS语言 + ArkUI框架 + 三层架构(Model/Service/Page)
- 数据策略:当前阶段使用Mock数据,后续接入真实AI大模型API
- 视觉规范:深色主题(#1A0A2E背景)、金色文字(#FFD700标题)、紫色点缀(#7C3AED按钮)
- 交互方式:用户输入信用卡名称和对比维度,点击按钮触发AI生成,展示结构化对比结果
- 交付标准:编译通过、页面渲染正常、输入/点击/展示功能完整、与现有应用风格一致
二、架构阶段(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 = []
// ... 其余字段已在声明时初始化
}
}
设计考量:
-
字段声明与初始化分离:在ArkTS中,类字段既可以在声明时初始化,也可以在构造函数中初始化。本项目采用双重初始化策略——声明时提供默认值,构造函数中再次确认,确保所有字段在任何情况下都有确定的值。
-
数组类型字段:
comparison、annual_fee、scenario_recommendation三个字段被设计为string[]类型,用于存储列表形式的对比数据。在ArkTS中,数组是唯一支持索引访问的数据结构,这与HarmonyOS的语法约束一致。 -
字符串类型字段:其余字段均为
string类型,用于存储单值数据。默认值为空字符串'',避免了null/undefined带来的运行时风险。 -
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
}
}
设计考量:
-
私有成员变量:
model字段使用private修饰,遵循ArkTS的封装原则。ArkTS不支持#私有标识符,必须使用private关键字。 -
输入参数类型:
Record<string, Object>替代了any类型。这是因为ArkTS不支持any和unknown类型,必须显式指定类型。Record<K, V>是ArkTS支持的少数实用类型之一。 -
Mock数据占位:当前
generateData方法返回硬编码的示例数据。在实际项目中,这里会替换为AI大模型API调用,通过HTTP请求获取AI生成的对比结果。 -
字符串转换:
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),从上到下依次为:
- Header区域:返回按钮 + 标题 + 装饰图标
- 塔罗牌装饰区域:三张卡片(过去/现在/未来)的交互元素
- 输入区域:信用卡名称输入框 + 对比维度输入框
- 按钮:触发AI数据生成
- 结果展示区域:条件渲染,仅在
showResult && resultData !== null时显示
2.8 异常处理策略
在ArkTS中,异常处理需要遵循以下原则:
- catch子句省略类型标注:ArkTS不支持catch子句中的类型标注,因为any和unknown类型不被支持。
try {
// 可能抛出异常的代码
} catch {
// 错误处理,无需类型标注
console.error('操作失败')
}
-
空值安全:使用
| null联合类型标记可能为空的值,如resultData: AI信用卡权益对比Data | null = null。在访问前通过!== null进行类型守卫。 -
条件渲染保护:在访问
this.resultData.comparison等数组属性前,先通过if (this.resultData.comparison)进行存在性检查,避免访问空值。
三、原子化阶段(Atomize):任务分解与执行计划
在架构设计完成后,将整个开发任务分解为若干可独立执行、可验证的原子任务。原子化分解的目的是降低每个任务的复杂度,使得每个任务都可以在短时间内完成并验证。
3.1 任务分解
任务1:创建Model数据模型
文件:entry/src/main/ets/apps/AI信用卡权益对比/AI信用卡权益对比Model.ets
执行内容:
- 定义
AI信用卡权益对比Data类 - 声明所有字段及其类型
- 实现构造函数初始化所有字段
- 使用
export关键字导出类
验收标准:
- 编译通过,无类型错误
- 所有字段都有明确的类型标注
- 支持通过
new AI信用卡权益对比Data()创建实例
任务2:实现Service服务层
文件:entry/src/main/ets/apps/AI信用卡权益对比/AI信用卡权益对比Service.ets
执行内容:
- 导入Model类
- 定义
AI信用卡权益对比Service类 - 实现
generateData方法 - 返回Mock数据作为AI输出样例
验收标准:
- 编译通过
- 调用
generateData返回正确的数据实例 - 输入参数正确处理
任务3:构建Page页面UI
文件:entry/src/main/ets/apps/AI信用卡权益对比/AI信用卡权益对比Page.ets
执行内容:
- 导入Model、Service和router
- 定义
@Entry @Component修饰的页面结构体 - 声明@State状态变量
- 构建UI布局(Header、输入区、按钮、结果区)
- 实现事件处理逻辑
验收标准:
- 编译通过
- 页面可正常渲染
- 输入、点击、结果展示功能完整
- 与现有应用视觉风格一致
任务4:注册路由配置
文件:entry/src/main/resources/base/profile/main_pages.json
执行内容:
- 在路由配置中添加AI信用卡权益对比页面的路径映射
验收标准:
- 路由配置正确
- 可通过
router.pushUrl跳转到该页面
任务5:集成到应用列表
文件:entry/src/main/resources/rawfile/apps/apps.json
执行内容:
- 在应用列表JSON中添加AI信用卡权益对比条目
- 配置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 功能验收标准
- 页面加载:页面正常渲染,Header显示"AI信用卡权益对比"标题
- 输入功能:两个TextInput组件可正常输入文字
- 按钮交互:点击"📱 塔罗占卜"按钮触发数据生成
- 结果展示:结果面板正确展示comparison、annual_fee、scenario_recommendation等数据
- 返回功能:点击"← 返回"可回到首页
- 塔罗牌交互:点击三张塔罗牌可切换选中状态
五、自动化执行阶段(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() {
更多推荐



所有评论(0)