基于HarmonyOS ArkTS的AI旅行规划助手:从零到一构建端侧智能应用
前言
在移动互联网的下半场,单纯的工具型App已经难以满足用户日益增长的需求。用户不再满足于"查看信息",而是期望应用能够"理解意图、主动服务"。这一趋势在旅行领域尤为明显——用户希望有了一个模糊的出行想法之后,App能自动帮他们完成从目的地推荐、行程规划、酒店航班预订到每日穿搭建议的全流程服务。
本文将深入剖析一个基于HarmonyOS ArkTS框架打造的AI旅行规划助手项目,从技术架构、设计模式、状态管理、AI Agent设计、API集成等多个维度,全面解读如何构建一个"小而美"的端侧智能应用。项目虽小,但涵盖了现代移动应用开发中数据建模、组件化设计、响应式UI、HTTP通信、路由管理等核心技术点,是学习HarmonyOS应用开发的优秀实践案例。
一、项目概览与技术栈
1.1 项目定位
本项目是一个面向C端用户的旅行规划助手,核心理念是"一句话生成旅行计划"——用户只需用自然语言描述出行想法(如"我下个月想去暖和的地方看海,预算5000元"),系统自动完成:
- 意图识别:分析用户身份(上班族/大学生/银发族/亲子家庭/情侣等)、出行目的、当前心情
- 目的地推荐:基于用户画像智能匹配目的地
- 行程生成:生成包含航班、酒店、每日活动的完整行程
- 细节完善:提供景点详情、美食推荐、天气查询、穿搭建议、旅行贴士等
1.2 技术栈一览
| 技术层面 | 技术选型 |
|---|---|
| 开发语言 | ArkTS(TypeScript超集) |
| 运行平台 | HarmonyOS 6.1.0 (API 23) |
| UI框架 | ArkUI 声明式UI |
| 构建工具 | Hvigor |
| 模块管理 | Stage模式 |
| HTTP通信 | @ohos.net.http |
| 路由管理 | @ohos.router |
| 日志系统 | @kit.PerformanceAnalysisKit (hilog) |
| 应用生命周期 | @kit.AbilityKit (UIAbility) |
| 窗口管理 | @kit.ArkUI (window) |
1.3 项目结构
huaweidemo/
├── AppScope/
│ └── app.json5 # 应用全局配置
├── entry/
│ ├── build-profile.json5 # 模块构建配置
│ └── src/main/
│ ├── module.json5 # 模块配置(权限、Ability声明)
│ ├── ets/
│ │ ├── entryability/
│ │ │ └── EntryAbility.ets # 应用入口Ability
│ │ ├── pages/
│ │ │ ├── Index.ets # 首页(输入+意图识别入口)
│ │ │ ├── IntentRecognition.ets # 意图识别确认页
│ │ │ ├── ItineraryDetail.ets # 行程详情页
│ │ │ └── EditPlan.ets # 行程编辑页
│ │ ├── components/
│ │ │ ├── InputSection.ets # 输入区域组件
│ │ │ ├── IntentDialog.ets # 意图对话组件
│ │ │ ├── PickerModal.ets # 通用选择弹窗
│ │ │ └── DestinationPickerModal.ets # 目的地选择弹窗
│ │ └── theme.ets # 统一主题系统
│ ├── resources/
│ │ └── base/
│ │ ├── element/
│ │ │ ├── string.json # 字符串资源(支持国际化)
│ │ │ └── color.json # 颜色资源
│ │ └── profile/
│ │ └── main_pages.json # 页面路由配置
│ └── rawfile/ # 原始资源文件(图片等)
└── hvigorfile.ts # 根构建配置
1.4项目演示




二、核心技术架构设计
2.1 声明式UI与组件化设计
ArkUI采用声明式UI范式,开发者只需描述UI的"最终状态",框架自动处理状态变化时的UI更新。本项目充分利用了这一特性,通过@State、@Prop、@Link等装饰器实现了高效的组件间通信。
主页面状态管理
在[Index.ets](file:///d:/HP/project/huaweidemo/entry/src/main/ets/pages/Index.ets)中,主页面通过@State管理了多个关键状态:
@State userInput: string = ''; // 用户输入文本
@State isListening: boolean = false; // 语音输入状态
@State currentStep: ResourceStr = '输入需求'; // 当前步骤提示
@State itinerary: Itinerary = new Itinerary(); // 行程数据
@State showDialog: boolean = false; // 是否显示意图对话
@State showLoading: boolean = false; // 是否显示加载动画
@State identifiedIdentity: ResourceStr = ''; // 识别的用户身份
@State identifiedPurpose: ResourceStr = ''; // 识别出行目的
@State identifiedMood: ResourceStr = '期待'; // 识别当前心情
@State bgStyle: string = '#F9FCFF'; // 动态背景色
这种设计将UI渲染与业务状态完全解耦。当任何一个@State变量发生变化时,ArkUI框架会自动触发相关UI组件的重新渲染,开发者无需手动操作DOM。
组件间通信模式
本项目采用了三种典型的组件通信模式:
- @Link 双向绑定:父组件将状态传递给子组件,子组件修改后父组件自动同步。例如
InputSection组件通过@Link userInput: string接收用户输入:
// InputSection.ets
export struct InputSection {
@Link userInput: string; // 双向绑定,子组件修改会自动同步到父组件
@Prop useTravelPreference: boolean = true; // 单向传递,只读
onGeneratePlan: () => void = () => {}; // 回调函数传递
}
- @Prop 单向传递:父组件将数据传给子组件展示,子组件不可修改。例如
IntentDialog通过@Prop接收意图识别结果:
export struct IntentDialog {
@Prop identifiedIdentity: ResourceStr = '';
@Prop identifiedPurpose: ResourceStr = '';
@Prop identifiedMood: ResourceStr = '期待';
@Prop destination: ResourceStr = '未选择';
}
- 回调函数:子组件通过回调函数将事件通知父组件,如
PickerModal的onSelect回调:
onSelect: (value: ResourceStr) => void = () => {};
onClose: () => void = () => {};
2.2 统一主题系统设计
在[theme.ets](file:///d:/HP/project/huaweidemo/entry/src/main/ets/theme.ets)中,项目定义了一套完整的Design Token系统,将颜色、字体、间距、圆角、阴影、动画等设计参数统一管理:
export class Theme {
static readonly colors: Colors = {
primary: '#91D5FF', // 主题色
primaryLight: '#BAE7FF', // 浅主题色
primaryDark: '#40A9FF', // 深主题色
secondary: '#6BD8D7', // 辅助色
accent: '#FFB86C', // 强调色
neutral: { // 中性色阶(9级)
neutral50: '#fafafa',
// ... neutral100 ~ neutral900
},
background: { primary: '#FAFCFF', secondary: '#fff', modal: '#fff9f0' },
text: { primary: '#333333', secondary: '#666666', hint: '#999999' },
status: { success: '#4caf50', warning: '#ff9800', error: '#f44336', info: '#2196f3' },
shadow: { light: 'rgba(0,0,0,0.05)', medium: 'rgba(0,0,0,0.1)', heavy: 'rgba(0,0,0,0.15)' }
};
static readonly typography: Typography = {
heading1: { fontSize: 32, fontWeight: FontWeight.Bold, lineHeight: 40 },
heading2: { fontSize: 24, fontWeight: FontWeight.Bold, lineHeight: 32 },
heading3: { fontSize: 20, fontWeight: FontWeight.Medium, lineHeight: 28 },
bodyLarge: { fontSize: 18, fontWeight: FontWeight.Medium, lineHeight: 26 },
body: { fontSize: 16, fontWeight: FontWeight.Normal, lineHeight: 24 },
bodySmall: { fontSize: 14, fontWeight: FontWeight.Normal, lineHeight: 20 },
caption: { fontSize: 12, fontWeight: FontWeight.Normal, lineHeight: 16 }
};
static readonly spacing: Spacing = {
xs: 4, sm: 8, md: 16, lg: 24, xl: 32, xxl: 48, xxxl: 64
};
static readonly borderRadius: BorderRadius = {
none: 0, sm: 4, md: 8, lg: 16, xl: 24, xxl: 32, full: 9999
};
static readonly shadows: Shadows = {
subtle: { radius: 4, color: 'rgba(0,0,0,0.05)', offsetX: 0, offsetY: 2 },
medium: { radius: 8, color: 'rgba(0,0,0,0.1)', offsetX: 0, offsetY: 4 },
strong: { radius: 16, color: 'rgba(0,0,0,0.15)', offsetX: 0, offsetY: 8 }
};
}
设计亮点:
- 中性色阶:9级色阶(neutral50 ~ neutral900)覆盖了从背景到文字的所有灰度需求,避免在组件中硬编码颜色值
- 语义化命名:使用
primary、secondary、accent、status等语义化名称,而非blue、green等具体颜色名,方便后续换肤 - 静态常量:使用
static readonly确保Theme在全局唯一且不可变,所有组件通过Theme.colors.primary引用,实现设计一致性 - 类型安全:通过TypeScript的
interface定义每种Token的结构,编译期即可发现引用错误
2.3 页面路由与导航设计
HarmonyOS的Stage模型使用@ohos.router进行页面导航。本项目共有4个页面,路由配置在main_pages.json中:
{"src": ["pages/Index", "pages/IntentRecognition", "pages/ItineraryDetail", "pages/EditPlan"]}
页面跳转流程:
Index(首页)
└─→ IntentRecognition(意图识别确认)
└─→ ItineraryDetail(行程详情)
└─→ EditPlan(行程编辑)
路由参数传递设计采用了强类型接口:
// Index.ets 中定义的路由参数接口
export interface IntentParams {
need: string; // 用户需求
userInput: string; // 用户原始输入
aiResponse: string; // AI响应文本
destination: string; // 选择的目的地
}
export interface TravelRouteParams {
need: string;
userIdentity: string;
travelPurpose: string;
travelMood?: string;
userInput?: string;
itinerary: string; // JSON序列化的行程数据
}
这种设计的好处是:
- 编译期检查:使用TypeScript接口定义参数结构,避免运行时字段名拼写错误
- 自文档化:接口本身就是参数文档,开发者一眼就能知道需要传递哪些字段
- 可扩展性:通过可选字段(
?)支持渐进式扩展
三、AI Agent设计模式
3.1 智能体架构
项目中最核心的设计是AI Agent模式(位于[Index.ets](file:///d:/HP/project/huaweidemo/entry/src/main/ets/pages/Index.ets#L893-L1059)中的AIAgent类)。它将自然语言理解、信息抽取、推荐生成、行程规划等能力封装为独立的智能体:
class AIAgent {
// 1. 信息抽取层:从用户输入中提取结构化信息
recognizeFlightInfo(userInput: string): FlightInfo | null { ... }
recognizeHotelInfo(userInput: string): HotelInfo | null { ... }
// 2. 意图理解层:理解用户意图并构建意图对象
understandIntent(userInput, userIdentity, travelPurpose, flightInfo, hotelInfo): Intent { ... }
// 3. 推荐引擎层:基于意图生成推荐
getDestinationRecommendation(intent: Intent): Destination { ... }
getFlightOptions(destination, intent): Array<Flight> { ... }
getHotelOptions(destination, intent): Array<Hotel> { ... }
getAttractions(destination): Array<Attraction> { ... }
// 4. 规划生成层:生成每日行程
generateDailyPlans(destination, intent, attractions): Array<DailyPlan> { ... }
// 5. 总结生成层:生成自然语言总结
async generateSummary(itinerary, destination, intent): Promise<string> { ... }
// 6. 外部API调用层
async fetchRealWeatherData(city: string): Promise<WeatherData | null> { ... }
// 主入口:处理完整请求
async processRequest(userInput, userIdentity, travelPurpose): Promise<PlanResult> {
const flightInfo = this.recognizeFlightInfo(userInput);
const hotelInfo = this.recognizeHotelInfo(userInput);
const intent = this.understandIntent(userInput, userIdentity, travelPurpose, flightInfo, hotelInfo);
const destination = this.getDestinationRecommendation(intent);
const flights = flightInfo ? [this.convertFlightInfo(flightInfo)] : this.getFlightOptions(destination, intent);
const hotels = hotelInfo ? [this.convertHotelInfo(hotelInfo)] : this.getHotelOptions(destination, intent);
const attractions = this.getAttractions(destination);
const dailyPlans = this.generateDailyPlans(destination, intent, attractions);
const itinerary = this.buildItinerary(destination, intent, flights, hotels, dailyPlans);
const summary = await this.generateSummary(itinerary, destination, intent);
return { summary, itinerary };
}
}
3.2 正则表达式信息抽取
recognizeFlightInfo和recognizeHotelInfo方法使用正则表达式从自然语言中提取结构化信息,这是端侧轻量级NLP的经典实践:
recognizeFlightInfo(userInput: string): FlightInfo | null {
const flightPatterns = [
/([A-Z]{2}\d{3,4})/, // 航班号:如 CA1234
/(\d{4}-\d{2}-\d{2})/, // 日期:如 2024-12-20
/(\d{1,2}:\d{2})到(\d{1,2}:\d{2})/, // 时间范围:如 08:00到11:30
/从(.+?)到(.+?)/ // 城市对:如 从北京到三亚
];
// 通过正则匹配提取航班信息 ...
}
这种方案的优势在于:
- 零依赖:不需要引入任何NLP库,完全在端侧执行
- 低延迟:正则匹配在毫秒级完成
- 可解释:规则清晰,便于调试和维护
3.3 基于用户画像的推荐引擎
项目的推荐引擎不再是一刀切的热门推荐,而是基于用户身份画像的精准匹配。在getSmartRecommendation方法中,系统根据用户身份、出行目的、当前心情三个维度构建推荐矩阵:
getSmartRecommendation(): string {
const identity = this.identifiedIdentity.toString();
const purpose = this.identifiedPurpose.toString();
const mood = this.identifiedMood.toString();
// 上班族 + 放松解压 → 大理
if (identity.includes('上班族') && (purpose.includes('放松') || purpose.includes('解压'))) {
return '大理';
}
// 大学生 + 极致性价比/穷游 → 桂林/厦门/西安/成都
if (identity.includes('大学生') && (purpose.includes('性价比') || purpose.includes('穷游'))) {
const budgetCities = ['桂林', '厦门', '西安', '成都'];
return budgetCities[Math.floor(Math.random() * budgetCities.length)];
}
// 银发族 + 文化探索 → 北京/西安/杭州/成都
if (identity.includes('银发') && (purpose.includes('文化') || purpose.includes('历史'))) {
const culturalCities = ['北京', '西安', '杭州', '成都'];
return culturalCities[Math.floor(Math.random() * culturalCities.length)];
}
// 亲子家庭 → 成都(熊猫)/三亚(海滩)/厦门(文艺)
if (identity.includes('亲子') || identity.includes('家庭')) {
const familyCities = ['成都', '三亚', '厦门', '桂林'];
return familyCities[Math.floor(Math.random() * familyCities.length)];
}
// ...
}
推荐策略的设计哲学:
| 用户画像 | 推荐偏好 | 设计依据 |
|---|---|---|
| 上班族 | 大理、三亚、厦门 | 慢节奏、放松解压、远离工作 |
| 大学生 | 桂林、西安、成都 | 性价比高、文化底蕴、社交属性 |
| 银发族 | 北京、杭州、桂林 | 文化景点、交通便利、节奏舒缓 |
| 亲子家庭 | 成都、三亚、桂林 | 熊猫乐园、海滩玩沙、自然风光 |
| 情侣 | 丽江、三亚、杭州 | 浪漫氛围、网红打卡、蜜月氛围 |
3.4 情感化交互设计
项目不仅关注功能实现,还精心设计了情感化交互。在getEmotionComfortMessage方法中,系统根据用户身份和心情生成个性化的安抚话术:
getEmotionComfortMessage(identity: string, mood: string, userInput: string): string {
// 疲惫的上班族 - 治愈与逃离
if (identity.includes('上班族') || mood === '疲惫' || userInput.includes('累')) {
return '亲爱的,辛苦了。这次我们不赶时间,只赶日落。去海边发发呆吧,工作群的消息先放一放。';
}
// 热血的大学生 - 震撼与性价比
if (identity.includes('大学生') || mood === '热血') {
return '青春没有售价,硬座直达拉萨!趁年轻,去看看祖国的大好河山,这趟旅程绝对是你简历上最酷的一笔!';
}
// 银发族 - 悠闲与怀旧
if (identity.includes('银发') || identity.includes('老年') || mood === '怀旧') {
return '岁月静好,您值得一段悠闲的旅程。让我们慢慢走,看看祖国的大好河山,品味每一处风景的独特韵味。';
}
// ...
}
这种情感化设计让用户感受到App不是在"冷冰冰地处理任务",而是在"温暖地陪伴用户",是产品体验从"能用"到"好用"的关键一步。
四、数据模型与领域驱动设计
4.1 领域模型设计
项目定义了一套完整的领域模型,涵盖行程规划的各个实体:
// 核心聚合根:行程
class Itinerary {
destination: string; // 目的地
startDate: string; // 开始日期
endDate: string; // 结束日期
budget: number; // 预算
flights: Array<Flight>; // 航班列表
hotels: Array<Hotel>; // 酒店列表
dailyPlans: Array<DailyPlan>; // 每日计划
userIdentity: string; // 用户身份
travelPurpose: string; // 出行目的
travelMood: string; // 出行心情
}
// 实体:航班
class Flight {
airline: string; // 航空公司
flightNumber: string; // 航班号
departure: string; // 出发城市
arrival: string; // 到达城市
departureTime: string; // 出发时间
arrivalTime: string; // 到达时间
price: number; // 价格
}
// 实体:酒店
class Hotel {
name: string; // 酒店名称
address: string; // 地址
pricePerNight: number; // 每晚价格
rating: number; // 评分
amenities: Array<string>; // 设施列表
}
// 实体:每日计划
class DailyPlan {
day: number; // 第几天
activities: Array<string>; // 活动列表
meals: Array<string>; // 餐饮列表
transportation: string; // 交通方式
weather: string; // 天气
clothingAdvice: string; // 穿搭建议
routeInfo: RouteInfo; // 路线信息
}
// 值对象:路线信息
class RouteInfo {
startPoint: string; // 起点
endPoint: string; // 终点
distance: string; // 距离
duration: string; // 耗时
steps: Array<RouteStep>; // 步骤
mapLink: string; // 地图链接
}
4.2 聚合根设计思路
Itinerary作为聚合根,包含了行程的全部信息。这种设计的优势在于:
- 数据一致性:对行程的修改都通过
Itinerary聚合根进行,确保航班、酒店、每日计划之间的数据一致性 - 序列化便利:
JSON.stringify(itinerary)即可将整个行程序列化为JSON字符串,便于路由传递和持久化存储 - 版本管理:聚合根可以携带版本号,支持行程数据的版本控制和增量更新
4.3 编辑模式下的行程项模型
在[ItineraryDetail.ets](file:///d:/HP/project/huaweidemo/entry/src/main/ets/pages/ItineraryDetail.ets)和[EditPlan.ets](file:///d:/HP/project/huaweidemo/entry/src/main/ets/pages/EditPlan.ets)中,项目定义了更细粒度的行程项模型:
interface ItineraryItem {
id: string; // 唯一标识
type: 'attraction' | 'restaurant' | 'transportation' | 'hotel' | 'activity'; // 类型
name: string; // 名称
description: string; // 描述
time: string; // 时间
period: TimePeriod; // 时间段(早上/上午/中午/下午/晚上/夜间)
location: string; // 位置
cost: number; // 费用
rating?: number; // 评分
icon: string; // 图标
attractionDetail?: AttractionDetail; // 景点详情(景点专属)
restaurantDetail?: RestaurantDetail; // 餐厅详情(餐饮专属)
}
这里的TimePeriod类型定义非常精妙:
type TimePeriod = 'morning' | 'forenoon' | 'noon' | 'afternoon' | 'evening' | 'night';
将一天划分为6个时段,使得行程编排更加精细。每个行程项归属于特定时段,用户可以按时间顺序查看和调整行程安排。
五、HTTP API集成与外部数据源
5.1 天气API集成
项目通过@ohos.net.http模块调用第三方天气API,实时获取目的地天气数据:
async fetchWeatherData(city: string): Promise<void> {
if (!city || city.trim() === '') return;
this.isLoadingWeather = true;
try {
const apiKey = '6d997a997fbf';
const url = `https://whyta.cn/api/tianqi?key=${apiKey}&city=${encodeURIComponent(city)}`;
const httpRequest = http.createHttp();
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
header: { 'Content-Type': 'application/json' },
connectTimeout: 60000,
readTimeout: 60000
});
if (response.responseCode === 200) {
this.weatherData = JSON.parse(response.result.toString()) as WeatherData;
}
httpRequest.destroy();
} catch (error) {
console.error('获取天气数据失败:', error);
}
this.isLoadingWeather = false;
}
关键设计点:
- 资源释放:无论成功失败,都调用
httpRequest.destroy()释放HTTP连接资源 - 超时设置:设置了60秒的连接超时和读取超时,避免网络不稳定时长时间挂起
- URL编码:使用
encodeURIComponent对中文城市名进行URL编码 - 响应式状态:通过
@State isLoadingWeather控制UI的加载状态显示
5.2 景点API集成
类似地,景点查询API也采用相同的设计模式:
async fetchScenicInfo(word: string): Promise<void> {
const url = `https://whyta.cn/api/tx/scenic?key=${apiKey}&word=${encodeURIComponent(word)}`;
// ... 相同的HTTP调用模式
}
API响应数据结构:
interface ScenicResponse {
code: number;
msg: string;
result: {
list: Array<{
name: string;
content: string;
province: string;
city: string;
}>;
};
}
interface WeatherData {
city: string;
temperature: string;
weather: string;
winddir: string;
windspeed: string;
humidity: string;
precip: string;
}
5.3 离线降级策略
项目在API调用失败时,设计了完善的离线降级策略。以景点详情为例,generateAttractionDetail方法为9个城市(大理、北京、上海、成都、西安、杭州、三亚、丽江、厦门、桂林)的数十个热门景点预置了离线数据:
generateAttractionDetail(name: string): AttractionDetail {
const destination = this.itinerary.destination;
// 大理景点
if (destination.includes('大理') || destination.includes('云南')) {
if (name === '洱海' || name.includes('洱海')) {
return {
needReservation: '无需预约',
openTime: '全天开放(建议8:00-18:00)',
ticketInfo: '环海公路免费,部分观景台收费10-20元',
tips: ['租电动车约60元/天,记得戴头盔', '带防晒霜和墨镜,紫外线强', ...],
suggestedDuration: '建议半日游(4-5小时),可分段进行',
workerFriendlyTip: '不用早起看日出,下午去光线更好,适合悠闲骑行'
};
}
// ... 更多景点
}
// 默认通用模板
return {
needReservation: '建议提前咨询或现场确认',
openTime: '09:00-17:00',
tips: ['穿舒适的鞋子', '注意天气变化', ...],
suggestedDuration: '建议游玩1.5-2小时',
workerFriendlyTip: '轻松游玩,不必赶时间,享受旅途'
};
}
这种离线预置数据的策略确保了:
- 无网络时仍能提供有价值的景点信息
- 首屏加载速度极快,无需等待API响应
- 在线API数据作为增强补充,而非必需依赖
六、动态UI与用户体验优化
6.1 时段感知的动态问候语
首页的问候语会根据当前时间动态变化,让用户感受到App的"生命力":
updateDynamicPrompt() {
const now = new Date();
const hour = now.getHours();
const day = now.getDay();
if (day === 1 && hour < 12) {
this.dynamicPrompt = '新的一周辛苦了,想去哪里透透气?';
} else if (day === 5 && hour >= 18) {
this.dynamicPrompt = '周末到了,是去拥抱山海,还是去城市漫步?';
} else if (hour < 12) {
this.dynamicPrompt = '早上好!今天想计划一次怎样的旅行?';
} else if (hour < 18) {
this.dynamicPrompt = '下午好!工作之余,有没有想去的地方?';
} else {
this.dynamicPrompt = '晚上好!是时候规划一次放松身心的旅行了';
}
}
设计亮点:
- 周末(周五晚上)触发特殊的"周末模式"问候语
- 周一早晨触发"关怀模式"问候语,站在用户角度体谅疲惫
- 不同时段使用不同的语气和内容,让每一次打开都有新鲜感
6.2 身份感知的加载提示
加载动画不仅是视觉上的等待反馈,还会根据用户身份展示不同的文案:
Text(
this.userIdentity.includes('上班族') ? '正在为你寻找治愈角落...' :
this.userIdentity.includes('大学生') ? '正在计算最优穷游路线...' :
'正在为你规划完美旅程...'
)
6.3 可编辑的行程系统
[EditPlan.ets](file:///d:/HP/project/huaweidemo/entry/src/main/ets/pages/EditPlan.ets)实现了完整的行程编辑功能,支持:
- 按天浏览:通过水平滚动的Tab切换不同天数的行程
- 添加行程:支持添加景点、餐饮、交通、活动四种类型
- 编辑行程:修改已有行程项的名称、时间、位置、费用
- 删除行程:移除不需要的行程项
- 数据持久化:通过
AppStorage在页面间传递编辑后的数据
saveAndBack() {
AppStorage.setOrCreate('updatedDayPlans', JSON.stringify(this.dayPlans));
router.back();
}
这种设计让用户不仅能"接受AI生成的计划",还能"自由调整和定制",真正实现了人机协作的旅行规划。
七、国际化与资源管理
7.1 字符串资源化
项目将所有用户可见的文本提取到string.json资源文件中,支持多语言切换:
{
"string": [
{ "name": "app_title", "value": "旅行规划助手" },
{ "name": "input_placeholder", "value": "告诉我你的旅行想法" },
{ "name": "morning_greeting", "value": "早上好!今天想计划一次怎样的旅行?" },
{ "name": "identity_office_worker", "value": "上班族" },
{ "name": "identity_college_student", "value": "大学生" },
{ "name": "purpose_relaxation", "value": "放松解压" },
{ "name": "purpose_budget_optimization", "value": "极致性价比" },
{ "name": "loading_office_worker", "value": "正在为你寻找治愈角落..." },
{ "name": "loading_college_student", "value": "正在计算最优穷游路线..." }
// ... 共240+个字符串资源
]
}
在代码中通过$r('app.string.xxx')引用,支持参数化:
Text($r('app.string.identity_label', { identity: this.identifiedIdentity }))
7.2 页面路由配置化
页面列表通过main_pages.json集中管理,而非在代码中硬编码:
{"src": ["pages/Index", "pages/IntentRecognition", "pages/ItineraryDetail", "pages/EditPlan"]}
八、项目技术亮点总结
8.1 架构设计亮点
| 方面 | 实践 | 价值 |
|---|---|---|
| 组件化 | 4个页面 + 4个可复用组件 | 高内聚低耦合,组件可独立测试和复用 |
| 主题系统 | 静态Design Token类 | 全局样式一致性,一次修改全局生效 |
| 状态管理 | @State/@Prop/@Link装饰器 | 声明式UI,数据驱动视图更新 |
| 路由设计 | 强类型接口参数传递 | 编译期检查,避免运行时参数错误 |
| AI Agent | 多层管道式处理架构 | 单一职责,可独立测试和替换各层 |
8.2 用户体验亮点
| 方面 | 实践 | 价值 |
|---|---|---|
| 情感化设计 | 时段问候语、身份感知提示、安抚话术 | 产品有温度,用户有共鸣 |
| 离线降级 | 预置9城数十景点离线数据 | 无网络也能用,首屏加载快 |
| 智能推荐 | 用户画像×目的×心情三维推荐 | 千人千面,推荐精准 |
| 可编辑行程 | 完整的增删改查功能 | 人机协作,用户有掌控感 |
| 多维关怀 | 穿搭建议、天气查询、贴心提醒 | 超出预期的服务体验 |
8.3 工程化亮点
| 方面 | 实践 | 价值 |
|---|---|---|
| 国际化 | 240+字符串资源化 | 多语言支持就绪 |
| 类型安全 | 全面使用TypeScript接口 | 编译期发现错误 |
| 资源管理 | HTTP连接正确释放 | 避免内存泄漏 |
| 错误处理 | try-catch + 降级策略 | 应用健壮性高 |
| 日志系统 | hilog分级日志 | 便于调试和线上追踪 |
九、技术展望与改进方向
虽然本项目已经是一个功能完备的旅行规划助手,但仍有以下可扩展方向:
9.1 接入真实AI大模型
当前AI Agent采用规则匹配和模拟数据,未来可接入真实的大语言模型(如盘古大模型),实现真正意义上的自然语言理解和行程生成。接入方式可以通过HarmonyOS的AI Kit实现端侧推理,或通过HTTP API调用云端模型。
9.2 分布式能力扩展
HarmonyOS的核心优势在于分布式能力。本项目可扩展:
- 多设备协同:手机规划行程,智能屏展示详情,手表推送行程提醒
- 跨设备数据同步:通过分布式数据管理,在多个设备间同步行程数据
- 碰一碰分享:通过NFC碰一碰,与同伴分享行程计划
9.3 地图与导航集成
当前行程中的路线信息(起点、终点、距离、耗时)仅为静态文本,可集成HarmonyOS的地图服务,实现:
- 地图可视化展示行程路线
- 实时导航到景点
- 周边推荐(餐厅、酒店、加油站等)
9.4 社交化功能
- 行程分享到社交平台
- 好友协同编辑行程
- 社区UGC攻略内容
十、总结
本文从项目架构、组件设计、AI Agent模式、数据模型、API集成、用户体验优化等多个维度,全面剖析了一个基于HarmonyOS ArkTS的AI旅行规划助手的技术实现。
这个项目虽小,但涵盖了现代移动应用开发的诸多核心实践:声明式UI与组件化设计、统一主题系统、强类型路由参数、管道式AI Agent架构、离线降级策略、情感化交互设计等。这些技术实践不仅适用于HarmonyOS开发,其设计思想同样可以迁移到Android(Jetpack Compose)、iOS(SwiftUI)、Flutter、React Native等跨平台框架中。
对于正在学习HarmonyOS应用开发的读者,本项目是一个极具参考价值的实践案例——它展示了一个"小而美"的应用如何从零开始,通过良好的架构设计和对细节的极致追求,打磨出兼具实用功能和情感温度的产品体验。
项目信息:本项目基于HarmonyOS 6.1.0 (API 23),使用ArkTS语言开发,采用Stage模型。项目地址见文首文件路径。
免责声明:本文中的AI Agent采用规则匹配和模拟数据实现,用于演示架构设计思路。生产环境建议接入真实的大语言模型API。# 基于HarmonyOS ArkTS的AI旅行规划助手:从零到一构建端侧智能应用
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)