周末计划生成:鸿蒙AI应用,智能规划你的完美周末

一、引言

“周末到了,去哪儿玩呢?”——这是每个周五下午困扰都市人的灵魂拷问。打开点评APP刷了两小时,收藏了十几家店,最后周末却瘫在沙发上一无所获。选择困难症、预算超支、行程冲突,这些痛点让本该放松的周末变成了另一种焦虑。

周末计划生成正是为解决这一难题而生的鸿蒙原生AI应用。它基于ArkTS声明式UI框架,通过三个简单输入——城市人数预算——AI在1.5秒内智能生成从周六到周日的完整活动安排,以半天为颗粒度,每项活动附带精确费用说明,真正做到"输入即规划"。

本文将从架构设计、鸿蒙技术深度解析、AI应用亮点、技术挑战与解决方案、用户体验设计等维度,深入剖析这款应用的实现细节与产品哲学。
在这里插入图片描述

二、应用架构设计

2.1 整体架构

┌──────────────────────────────────┐
│  WeekendPlanPage.ets             │
│  (@Entry @Component)             │
│  @State: cityText, peopleCount,  │
│          budgetText, currentData  │
├──────────────────────────────────┤
│  WeekendPlanModel.ets            │
│  PlanEntry / WeekendData         │
│  WPMessage 消息队列模型           │
├──────────────────────────────────┤
│  WeekendPlanService.ets          │
│  getWeekendPlan() 业务逻辑       │
│  城市×人数×预算知识库             │
└──────────────────────────────────┘

2.2 页面结构组件树

Column (根容器, 紫色主题背景)
├── @Builder buildHeader()
│   ├── 图标 + 标题 + 副标题
│   └── 重置按钮 (条件渲染)
├── 城市输入: TextInput
│   └── onChange → @State cityText
├── 人数选择器: Stepper组件
│   ├── "-" 减少按钮
│   ├── 数字显示
│   └── "+" 增加按钮
├── 预算输入: TextInput
│   └── onChange → @State budgetText
├── 生成按钮 (条件: cityText+budgetText均非空)
├── Loading提示
└── Scroll → buildResultCard (条件: currentData非空)
    └── @Builder 时间轴卡片

2.3 数据模型

export class PlanEntry {
  slot: string      // 时间段标识:"周六上午"、"周六下午"、"周六晚上"...
  activity: string  // 活动描述:"参观外滩,感受上海的城市风光"
  cost: string      // 费用说明:"免费 / 约50元"
}

export class WeekendData {
  plan: PlanEntry[]  // 完整的周末行程数组
}

三、鸿蒙技术深度解析

3.1 Stepper 自增/自减组件的实现

本应用中的人数选择器采用Stepper(步进器)设计,通过自增自减按钮实现人数调整,这是鸿蒙ArkTS中为数不多需要自定义实现的交互组件:

@State peopleCount: number = 2

Row() {
  // 减少按钮
  Text('-')
    .fontSize(20)
    .fontWeight(FontWeight.Bold)
    .fontColor(COLOR_PRIMARY)
    .width(36).height(36)
    .textAlign(TextAlign.Center)
    .backgroundColor(COLOR_SELECTED_BG)
    .borderRadius(18)
    .onClick(() => { if (this.peopleCount > 1) { this.peopleCount-- } })

  // 数字显示
  Text(`${this.peopleCount}`)
    .fontSize(20)
    .fontWeight(FontWeight.Bold)
    .fontColor(COLOR_TEXT)
    .width(60)
    .textAlign(TextAlign.Center)

  // 增加按钮
  Text('+')
    .fontSize(20)
    .fontWeight(FontWeight.Bold)
    .fontColor(COLOR_PRIMARY)
    .width(36).height(36)
    .textAlign(TextAlign.Center)
    .backgroundColor(COLOR_SELECTED_BG)
    .borderRadius(18)
    .onClick(() => { if (this.peopleCount < 10) { this.peopleCount++ } })
}
.width('100%')
.padding({ left: 16, top: 4, bottom: 8 })
.justifyContent(FlexAlign.Center)

这个Stepper实现的关键设计要点:

  • 边界控制:通过 peopleCount > 1peopleCount < 10 限制人数范围在1-10之间,防止无效操作
  • 视觉反馈:按钮使用 COLOR_SELECTED_BG(浅紫)背景,与主色调形成对比
  • 居中布局:通过 FlexAlign.Center 将Stepper整体居中,符合移动端输入习惯
  • 响应式更新:每次点击触发 @State peopleCount 变化,UI自动更新数字显示

3.2 @Builder 时间轴卡片 —— 信息可视化设计

周末计划生成的结果展示采用了时间轴卡片的设计范式,这是本应用UI设计中最具特色的部分:

@Builder
buildResultCard(data: WeekendData) {
  Column() {
    Text('📅 周末行程安排')
      .fontSize(16)
      .fontWeight(FontWeight.Bold)

    ForEach(data.plan, (entry: PlanEntry, idx: number) => {
      Row() {
        // 左侧:时间标签(固定宽度)
        Column() {
          Text(entry.slot)
            .fontSize(14).fontWeight(FontWeight.Bold)
            .fontColor('#FFFFFF')
            .padding({ left: 10, right: 10, top: 4, bottom: 4 })
            .backgroundColor(COLOR_PRIMARY)
            .borderRadius(12)
        }
        .margin({ right: 10 })
        .width(70)

        // 右侧:活动内容 + 费用标签
        Column() {
          Text(entry.activity)
            .fontSize(14).fontWeight(FontWeight.Bold)
            .fontColor(COLOR_TEXT)
            .margin({ bottom: 2 })
          Text(entry.cost)
            .fontSize(12)
            .fontColor(COLOR_TEXT_SEC)
            .padding({ left: 6, right: 6, top: 2, bottom: 2 })
            .backgroundColor(COLOR_SELECTED_BG)
            .borderRadius(6)
        }
        .layoutWeight(1)
      }
      .width('100%')
      .padding(12)
      .backgroundColor(COLOR_CARD)
      .borderRadius(12)
      .border({ width: 1, color: COLOR_BORDER })
      .margin({ bottom: 8 })
    }, (_: PlanEntry, idx: number) => `plan_${idx}`)
  }
}

时间轴卡片的设计亮点:

  • 左时间右内容:左侧固定70px宽度的时间标签(“周六上午”“周六下午”),右侧使用 layoutWeight(1) 填充剩余空间,形成呼吸感
  • 紫色时间标签:时间标签采用主色调背景 + 白色文字,视觉突出
  • 费用胶囊:费用说明采用浅紫底色胶囊标签,与时间标签形成颜色呼应但层级更低

3.3 多条件联动验证

本应用的生成按钮需要同时满足三个条件:城市已填写、预算已填写(人数有默认值2,非必填)。在代码中通过 if 条件渲染实现:

if (this.cityText !== '' && this.budgetText !== '') {
  Text('生成周末计划')
    .fontSize(16)
    .fontWeight(FontWeight.Bold)
    .fontColor('#FFFFFF')
    .padding({ left: 32, right: 32, top: 12, bottom: 12 })
    .backgroundColor(COLOR_PRIMARY)
    .borderRadius(24)
    .margin({ top: 16 })
    .onClick(() => { this.onGenerate() })
}

这里的设计决策是:人数为可选字段(有默认值2),所以不纳入必填验证。用户可以选择不操作人数Stepper,使用默认值直接生成计划。

3.4 加载状态与用户体验

if (this.isLoading) {
  Row() {
    Text('🎉 正在规划周末行程……')
      .fontSize(13)
      .fontColor(COLOR_TEXT_SEC)
      .padding(12)
  }
  .width('100%')
  .padding({ left: 16 })
}

加载提示使用 🎉 表情符号配合自然语言文案,传递积极、期待的情绪。这种"拟人化加载"比传统的进度条或转圈更符合生活服务类应用的调性。

四、AI应用亮点分析

4.1 三档预算智能适配

AI的预算处理能力是周末计划生成的核心亮点。虽然前端输入的是具体数字(如800元),但AI在内部将其映射为低/中/高三档预算,并据此调整活动推荐策略:

预算档位 金额范围(2人) 活动特征
低预算 0-500元 免费公园、博物馆、野餐、骑行
中预算 500-1500元 主题乐园、特色餐厅、短途景点
高预算 1500元以上 高端餐厅、自驾游、付费活动体验

4.2 双日行程的节奏设计

AI生成的周末计划覆盖周六和周日两天,以半天为颗粒度(上午/下午/晚上),共6个时间段。节奏上遵循"张弛有度"原则:

  • 周六上午:适度活动,轻松开启周末
  • 周六下午:核心活动,精力最充沛时段
  • 周六晚上:娱乐休闲,享受夜生活
  • 周日上午:轻松惬意,避免疲劳
  • 周日下午:收尾活动,为周一做准备
  • 周日晚上:休整恢复,保证充足休息

4.3 费用逐项列明

每项活动都附带了明确的费用说明,让用户对整体花费有清晰预期:

  • 免费活动标注:“免费”
  • 估算费用标注:“约50元/人"或"约200元(含门票)”
  • 精确费用标注:根据人数自动计算总价

这种透明化的费用展示策略,让预算控制变得直观可控。

五、关键技术挑战与解决方案

5.1 挑战一:数字输入的类型安全

问题TextInput 的 onChange 回调返回的是字符串类型,而AI需要的是数值类型进行预算档位判断。

解决方案:在 onGenerate() 中将字符串转换为数值:

private onGenerate(): void {
  // 将字符串转为数字传给service
  const budget = parseInt(this.budgetText) || 0
  const data = this.service.getWeekendPlan(this.cityText, this.peopleCount, this.budgetText)
  // ...
}

同时,人数选择器直接使用 @State peopleCount: number = 2 的数值类型,避免了类型转换的问题。

5.2 挑战二:Stepper边界的用户体验

问题:人数达到下限(1)或上限(10)时,继续点击按钮会有边界反馈。

解决方案

// 下限保护
if (this.peopleCount > 1) { this.peopleCount-- }

// 上限保护
if (this.peopleCount < 10) { this.peopleCount++ }

虽然没有使用disable样式禁用按钮,但这种"静默保护"的设计更符合移动端的直觉——用户按了没反应自然会意识到到边界了。

5.3 挑战三:长时间行程的展示可读性

问题:两天的行程(6个时间段)在手机屏幕上可能会显得冗长拥挤。

解决方案:使用 Scroll 包裹结果区域,通过 layoutWeight(1) 确保可滚动区域占据合理空间。每个时间卡片保持统一高度和间距,视觉上形成节奏感。

六、用户体验设计

6.1 色彩心理学

周末计划生成采用紫色作为主色调(#D946EF),传递出创意、愉悦、放松的品牌感知:

  • 紫色代表着想象力和创造力,与"规划美好周末"的应用定位吻合
  • 浅紫背景 #FDF2FC 营造出柔和、温馨的视觉氛围
  • 紫色时间标签与绿色费用标签形成冷暖对比,增强信息层次

6.2 输入流程设计

三个输入字段的排列顺序遵循从抽象到具体的逻辑:

城市(大范围)→ 人数(规模)→ 预算(约束)

这种顺序符合人类规划活动的自然思维流程——先决定去哪儿,再考虑和谁去,最后思考花多少钱。

6.3 结果的信息架构

时间轴卡片的信息层级:

📅 周末行程安排
├── [周六上午] 参观外滩,感受城市风光
│              免费
├── [周六下午] 游览豫园和城隍庙
│              约30元/人
├── ...

左侧时间标签的固定宽度(70px)设计确保所有卡片的时间信息保持对齐,形成清晰的视觉节奏。

七、总结

周末计划生成通过鸿蒙ArkTS声明式UI框架,优雅地实现了一个"输入即规划"的AI生活服务应用。@State 状态管理驱动下,三个输入维度的联动验证、Stepper步进器的高效交互、时间轴卡片的可视化展示,共同构成了完整的产品体验闭环。

从AI产品设计角度来看,预算智能分档、双日行程节奏设计、费用透明化展示三大亮点,让周末计划生成跳出了简单的"活动推荐"范畴,进化为一个真正理解"如何规划一个美好周末"的智能助手。未来如果接入真实的大模型API,还可以实现基于天气、实时交通、个人兴趣偏好等更多维度的个性化推荐,让每个周末都值得期待。

Logo

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

更多推荐