React Native鸿蒙,HarmonyOS ArkTS API 24 useEffect的返回清理函数对应鸿蒙组件的onDestroy生命周期
在智慧医疗场景下,个性化用药方案管理应用需要兼顾医疗数据的精准性、用药风险的实时检测以及多终端的适配能力。鸿蒙系统凭借分布式全场景架构,成为医疗应用跨端部署的核心载体,而React Native则为这类应用提供了“一次开发、多端运行”的技术底座。本文将从数据模型设计、核心业务逻辑实现、UI适配到鸿蒙跨端兼容的底层逻辑,全方位拆解这款个性化用药方案应用的技术实现,剖析React Native与鸿蒙生态融合的关键技术要点。
跨端架构
这款个性化用药方案应用的核心架构遵循React Native的“通用抽象层+平台适配层”设计理念,所有核心功能均基于React Native的通用API(如View、TextInput、Modal)和Hooks体系构建,未引入任何平台专属代码,这是实现鸿蒙跨端兼容的核心前提。
从底层适配逻辑来看,React Native for HarmonyOS框架会将React Native的通用组件无缝映射为鸿蒙ArkUI的原生组件:TouchableOpacity对应鸿蒙的Button组件,TextInput映射为鸿蒙的TextInput原生控件,Modal转换为鸿蒙的Dialog组件,Alert则调用鸿蒙的系统弹窗能力。这种映射机制保证了UI渲染和交互逻辑在鸿蒙设备上的一致性,同时规避了因平台差异导致的代码碎片化问题。例如,应用中用于展示药品详情的Modal组件,在鸿蒙手机、平板、智慧屏等不同形态设备上,都会按照鸿蒙的交互规范渲染为原生模态框,既保留了医疗应用的操作安全性,又符合鸿蒙系统的交互体验。
此外,应用通过Dimensions.get('window')获取设备屏幕尺寸,该API在鸿蒙系统中会被适配为鸿蒙的getWindowSize原生能力,保证了不同屏幕尺寸鸿蒙设备(如手机、平板)上的布局一致性,尤其适配了用药方案在大屏设备上的完整展示和小屏设备上的精简呈现需求。
强类型数据模型:
医疗数据的精准性是用药管理应用的核心要求,代码中通过TypeScript构建了多层级的强类型数据模型,从用户档案、药品信息到用药方案、药品相互作用,形成了闭环的医疗数据体系,既规避了前端开发中的类型错误,又在跨端编译阶段拦截了数据格式偏差。
// 用户档案模型:基础信息标准化
type User = {
id: string;
name: string;
age: number; // 数值型年龄,为剂量适配提供基础
gender: string; // 字符串型性别,兼容不同医疗场景的描述需求
};
// 药品核心模型:用药信息结构化
type Medicine = {
id: string;
name: string;
description: string;
dosage: string; // 字符串型剂量,兼容mg、ml等多单位描述
frequency: string; // 用药频率,适配"每日三次"等自然语言描述
time: string; // 用药时间,满足医疗场景的精准表述
};
// 关联模型:用户-药品的业务闭环
type MedicationPlan = {
id: string;
userId: string;
medicines: Medicine[]; // 多药品集合,适配组合用药场景
};
这些类型定义严格约束了数据的格式和类型,在鸿蒙系统中,React Native的TypeScript编译器会对JS层与鸿蒙ArkTS层之间的数据交互进行类型校验。例如,药品剂量、用药频率等核心参数在跨端传递时,会被强制校验为字符串类型,避免了因鸿蒙ArkTS的静态类型特性与JavaScript动态类型特性不兼容导致的用药信息展示错误。同时,时间、剂量等字段采用字符串类型存储,兼顾了医疗数据的可读性和跨端兼容性,符合医疗行业的数据展示规范。
应用的核心业务逻辑(药品添加、相互作用检测、用药方案管理)均基于React Hooks(useState、useEffect)实现,这种轻量级的状态管理方式完美适配React Native的跨端生命周期模型,同时与鸿蒙组件的生命周期深度融合。
状态设计
应用通过useState管理核心数据状态,采用“不可变更新”的方式修改状态,避免了引用类型数据在跨端环境下的共享冲突。例如,添加新药品到用药方案时,通过解构赋值创建新数组副本:
setMedicationPlans(prevPlans =>
prevPlans.map(plan =>
plan.userId === selectedUser
? { ...plan, medicines: [...plan.medicines, newMed] }
: plan
)
);
这种不可变更新策略在鸿蒙系统中尤为重要——鸿蒙的分布式数据管理要求数据副本的一致性,而不可变更新保证了每次状态变更都会生成新的数据源,避免了多端数据同步时的冲突问题。
药品相互作用自动检测:
应用通过useEffect实现每分钟一次的药品相互作用自动检测,这一逻辑在鸿蒙系统中能够稳定运行的核心原因在于:setInterval/clearInterval是React Native封装的通用定时器API,已适配鸿蒙的任务调度机制;useEffect的返回清理函数对应鸿蒙组件的onDestroy生命周期,确保定时器在组件卸载时被销毁,避免鸿蒙设备的内存泄漏。
useEffect(() => {
const interval = setInterval(() => {
const randomMedicine1 = medicines[Math.floor(Math.random() * medicines.length)];
const randomMedicine2 = medicines[Math.floor(Math.random() * medicines.length)];
const interaction = drugInteractions.find(i =>
(i.medicine1 === randomMedicine1.name && i.medicine2 === randomMedicine2.name) ||
(i.medicine1 === randomMedicine2.name && i.medicine2 === randomMedicine1.name)
);
if (interaction) {
Alert.alert('药品相互作用警告', `检测到${randomMedicine1.name}与${randomMedicine2.name}之间存在相互作用: ${interaction.interaction}`);
}
}, 60000);
return () => clearInterval(interval); // 对应鸿蒙组件销毁生命周期
}, [users, medicines, drugInteractions]);
检测逻辑中使用的数组find方法是ES6通用API,在鸿蒙系统中会被React Native框架转换为ArkTS的数组检索逻辑,保证了不同平台下检索结果的一致性,避免了用药风险检测的遗漏。
应用的UI层基于React Native的StyleSheet统一管理样式,既保证了鸿蒙系统中的原生渲染效果,又兼顾了医疗应用对数据展示清晰性、操作安全性的特殊要求。
样式系统
StyleSheet将CSS样式抽象为跨平台的样式对象,核心样式属性(如flex、borderRadius、padding)在鸿蒙系统中会被精准转换为ArkUI的布局属性。例如:
const styles = StyleSheet.create({
section: {
backgroundColor: '#ffffff',
marginHorizontal: 16,
borderRadius: 12,
padding: 16,
// 阴影适配:elevation适配鸿蒙/Android,shadow系列适配iOS
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
input: {
flex: 1,
backgroundColor: '#f0f9ff',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8,
fontSize: 14,
color: '#0c4a6e',
}
});
其中,elevation属性在鸿蒙系统中会被解析为原生的阴影层级,borderRadius则适配鸿蒙的圆角渲染规则,保证了UI视觉效果的跨端一致性。同时,医疗场景专属的浅蓝主题(#f0f9ff)既符合医疗应用的视觉规范,又适配鸿蒙系统的色彩体系。
交互组件的医疗场景
核心交互组件TouchableOpacity在鸿蒙系统中会被渲染为具备原生点击反馈的按钮,选中态的selectedCard样式(边框高亮)能够清晰标识当前选择的用户/药品,符合医疗应用“操作可追溯、状态可识别”的核心要求。用于录入药品信息的TextInput组件采用多行多列布局,适配药品名称、剂量、频率等多维度信息的录入,在鸿蒙设备上保证了输入框的响应速度和输入体验,避免因平台输入组件差异导致的信息录入错误。
当前代码已实现基础的鸿蒙跨端兼容,在生产环境中,可针对鸿蒙系统的特性进行深度优化,进一步提升医疗应用的体验:
1. 高性能列表
应用中用药方案、药品相互作用等列表采用ScrollView + map的方式渲染,在鸿蒙系统中面对大量历史用药数据时可能出现卡顿。可替换为React Native的FlatList组件,该组件在鸿蒙系统中会适配ArkUI的List原生组件,实现按需渲染和组件复用,通过getItemLayout优化列表滚动性能,尤其适合展示用户长期的用药记录和提醒信息。
2. 鸿蒙原生
用药提醒是医疗应用的核心功能,可通过React Native的Native Module机制封装鸿蒙的NotificationKit和AlarmManager原生API,将应用中的漏服补服提醒对接鸿蒙的系统级通知能力。例如,将MissedDoseReminder中的补服时间同步到鸿蒙的系统闹钟,实现跨鸿蒙设备(手机、智能手表)的用药提醒同步,充分利用鸿蒙的分布式能力提升用药依从性。
3. 分布式用药数据同步
基于鸿蒙的分布式数据管理能力,可通过React Native的跨端通信机制,实现用药数据在多鸿蒙设备间的同步。例如,用户在手机上编辑的用药方案,可实时同步到鸿蒙平板的医生端和智能手表的提醒模块,医护人员可通过平板查看用户的用药记录,用户则通过手表接收用药提醒,形成“患者-医护-设备”的闭环管理。
这款基于React Native开发的个性化用药方案应用,通过强类型数据模型、React Hooks状态管理和通用UI组件设计,构建了具备完整鸿蒙跨端兼容能力的医疗应用架构,核心技术要点可总结为:
- 通用API选型是实现鸿蒙兼容的基础,基于React Native通用组件构建核心逻辑,规避平台专属代码,保证了UI和交互的跨端一致性;
- TypeScript强类型约束不仅提升医疗数据的精准性,更适配鸿蒙ArkTS的静态类型特性,避免跨端数据交互中的类型错误;
- React Hooks状态管理与鸿蒙组件生命周期深度融合,保障了药品相互作用检测等周期性任务的跨端稳定运行;
- 统一的StyleSheet样式系统实现了UI在鸿蒙设备上的原生渲染,兼顾医疗应用的数据展示清晰性和操作安全性。
在医疗健康领域,精准的用药管理对患者康复和安全至关重要。本文将深入剖析一个基于 React Native 构建的个性化用药方案应用,探讨其技术实现细节及鸿蒙跨端能力的应用。
技术选型
该应用采用了现代 React Native 函数式组件架构,通过 TypeScript 类型系统和 React Hooks 实现了一个功能完整的个性化用药管理系统。核心技术栈包括:
- React Native:作为跨端开发框架,提供了统一的组件 API,确保应用在 iOS、Android 及鸿蒙平台上的一致性体验
- TypeScript:通过严格的类型定义增强代码可维护性,明确了数据结构和组件接口
- React Hooks:使用 useState 管理应用状态,useEffect 处理副作用逻辑,实现了声明式的状态管理
- Base64 图标:采用 Base64 编码的图标资源,避免了不同平台资源格式的差异,提高了跨端兼容性
- 响应式布局:使用 Dimensions API 获取屏幕尺寸,实现适配不同设备的响应式界面
数据模型
应用通过 TypeScript 接口定义了五个核心数据类型,构建了完整的医疗数据模型体系:
// 用户类型
type User = {
id: string;
name: string;
age: number;
gender: string;
};
// 药品类型
type Medicine = {
id: string;
name: string;
description: string;
dosage: string;
frequency: string;
time: string;
};
// 用药方案类型
type MedicationPlan = {
id: string;
userId: string;
medicines: Medicine[];
};
// 药品相互作用类型
type DrugInteraction = {
id: string;
medicine1: string;
medicine2: string;
interaction: string;
};
// 漏服补服提醒类型
type MissedDoseReminder = {
id: string;
userId: string;
medicineId: string;
missedTime: string;
rescheduleTime: string;
};
这种强类型设计不仅提高了代码可读性,也为鸿蒙跨端适配提供了清晰的数据契约,确保不同平台间数据传递的一致性。数据模型的设计充分考虑了医疗场景的特殊性,包含了患者基本信息、药品详细信息、用药方案、药品相互作用警告以及漏服提醒等核心业务数据。
状态管理
应用使用 useState Hook 管理多个复杂状态,包括用户列表、药品列表、用药方案、药品相互作用、漏服提醒等:
const [users] = useState<User[]>([
{
id: '1',
name: '李先生',
age: 45,
gender: '男'
},
{
id: '2',
name: '王女士',
age: 32,
gender: '女'
}
]);
// 其他状态定义...
特别值得注意的是,应用通过 useEffect 实现了药品相互作用的自动检测机制:
// 自动检测药品相互作用
useEffect(() => {
const interval = setInterval(() => {
const randomUser = users[Math.floor(Math.random() * users.length)];
const randomMedicine1 = medicines[Math.floor(Math.random() * medicines.length)];
const randomMedicine2 = medicines[Math.floor(Math.random() * medicines.length)];
const interaction = drugInteractions.find(i =>
(i.medicine1 === randomMedicine1.name && i.medicine2 === randomMedicine2.name) ||
(i.medicine1 === randomMedicine2.name && i.medicine2 === randomMedicine1.name)
);
if (interaction) {
Alert.alert('药品相互作用警告', `检测到${randomMedicine1.name}与${randomMedicine2.name}之间存在相互作用: ${interaction.interaction}`);
}
}, 60000);
return () => clearInterval(interval);
}, [users, medicines, drugInteractions]);
这种基于时间间隔的自动检测机制,模拟了真实场景中药品相互作用的实时监控,为患者用药安全提供了技术保障。同时,通过 useEffect 的清理函数,确保了定时器在组件卸载时被正确清除,避免了内存泄漏。
在 React Native 鸿蒙跨端开发中,该应用体现了以下关键技术点:
- 组件兼容性:使用 React Native 核心组件(如 View、Text、TouchableOpacity、ScrollView、Modal 等),确保在鸿蒙系统上的兼容性
- 资源管理:通过 Base64 编码的图标资源,避免了不同平台资源格式的差异,提高了跨端部署的一致性
- 尺寸适配:使用 Dimensions API 获取屏幕尺寸,实现响应式布局,适应不同设备屏幕
- 状态管理:采用 React Hooks 进行状态管理,保持跨平台代码一致性
- 类型安全:TypeScript 类型定义确保了数据结构在不同平台间的一致性
- API 调用:使用 React Native 统一的 API 调用方式,如 Alert 组件,确保在鸿蒙平台上的正确显示
药品管理功能
应用实现了药品的添加和管理功能,通过表单输入收集药品信息,并将其添加到用户的用药方案中:
const handleAddMedicine = () => {
if (newMedicine.name && newMedicine.description && newMedicine.dosage && newMedicine.frequency && newMedicine.time && selectedUser) {
const newMed: Medicine = {
id: (medicines.length + 1).toString(),
name: newMedicine.name,
description: newMedicine.description,
dosage: newMedicine.dosage,
frequency: newMedicine.frequency,
time: newMedicine.time
};
setMedicines([...medicines, newMed]);
setMedicationPlans(prevPlans =>
prevPlans.map(plan =>
plan.userId === selectedUser
? { ...plan, medicines: [...plan.medicines, newMed] }
: plan
)
);
setNewMedicine({ name: '', description: '', dosage: '', frequency: '', time: '' });
Alert.alert('添加成功', '新的药品已添加到用药方案中');
} else {
Alert.alert('提示', '请选择用户并填写完整的药品信息');
}
};
药品信息查看功能
应用提供了药品详细信息的查看功能,通过模态框展示药品的各项属性:
const handleViewMedicine = (medicineId: string) => {
const medicine = medicines.find(m => m.id === medicineId);
if (medicine) {
setModalContent(`药品名称: ${medicine.name}\n描述: ${medicine.description}\n剂量: ${medicine.dosage}\n频率: ${medicine.frequency}\n时间: ${medicine.time}`);
setIsModalVisible(true);
}
};
应用实现了基于用户的用药方案管理,每个用户可以有多个药品组成的个性化用药方案,系统会自动检测方案中的药品相互作用,确保用药安全。
应用通过自动检测机制,实时监控药品之间的相互作用,为患者用药安全提供了技术保障。检测逻辑考虑了药品配对的双向性,确保无论药品顺序如何都能准确检测到相互作用。
应用实现了漏服补服提醒功能,通过漏服补服提醒类型,提高患者用药依从性。系统会记录漏服时间和重新安排的服药时间,确保患者能够及时补服药物。
应用的 UI 设计遵循了现代移动应用的设计原则,使用了以下组件和交互模式:
- 安全区域:通过 SafeAreaView 确保内容显示在安全区域内,适应不同设备的屏幕刘海和底部指示条
- 滚动视图:通过 ScrollView 实现内容的垂直滚动,适应不同长度的药品列表和用药方案
- 卡片布局:使用 TouchableOpacity 和 View 组合实现卡片式列表项,提供清晰的视觉层次和交互反馈
- 模态框:通过 Modal 组件展示药品详情和用药方案信息
- 交互反馈:使用 Alert 组件提供操作反馈和药品相互作用警告
- 响应式设计:根据屏幕尺寸动态调整布局,确保在不同设备上的良好显示效果
- 跨端架构:基于 React Native 构建,实现了一次编码多平台运行的目标,特别关注了鸿蒙平台的适配
- 类型安全:全面使用 TypeScript 类型定义,提高代码质量和可维护性,确保医疗数据的准确性
- 药品相互作用检测:实现了自动检测药品相互作用的功能,为患者用药安全提供了技术保障
- 个性化用药方案:根据用户信息和药品特性,为每个用户提供个性化的用药方案
- 漏服提醒管理:通过漏服补服提醒功能,提高患者用药依从性
- 模块化设计:通过清晰的类型定义和函数划分,实现了代码的模块化,提高了可维护性
- 实时数据反馈:通过即时的 Alert 反馈,增强用户操作体验
- 数据结构设计:通过嵌套的数据结构,如用药方案包含药品,实现了复杂医疗数据的有效组织
- 自动检测机制:使用 setInterval 实现了药品相互作用的定期自动检测,模拟了真实的医疗监控场景
在实际应用中,还可以考虑以下性能优化策略:
- 状态管理优化:对于大型应用,可以考虑使用 Redux 或 Context API 进行全局状态管理,提高状态更新的效率
- 组件拆分:将大型组件拆分为更小的可复用组件,提高渲染性能和代码可维护性
- 数据缓存:对用户数据和药品信息进行本地缓存,减少重复计算和网络请求
- 动画性能:使用 React Native 的 Animated API 实现流畅的过渡动画,提升用户体验
- 内存管理:确保及时清理不再使用的状态和事件监听器,避免内存泄漏
- 网络优化:对于实际应用中的远程数据同步,实现合理的网络请求策略,如批量上传、增量同步等
- 计算优化:对于药品相互作用检测等频繁操作,可以考虑使用 memoization 技术缓存计算结果
- 列表优化:对于长列表,使用 FlatList 组件替代 ScrollView,提高渲染性能
在开发过程中,可能面临的技术挑战及解决方案:
- 鸿蒙平台适配:通过使用 React Native 核心组件和统一的 API 调用方式,确保应用在鸿蒙平台上的兼容性
- 药品相互作用数据更新:建立药品相互作用数据库的定期更新机制,确保数据的准确性和时效性
- 实时提醒功能:结合本地推送通知和后台任务,实现准确的用药提醒功能
- 数据安全:实现医疗数据的加密存储和传输,保护患者隐私
- 离线功能:实现基本的离线操作能力,确保在网络不稳定情况下的正常使用
- 性能优化:针对不同设备性能差异,实现自适应的性能优化策略,确保在中低端设备上的流畅运行
- 多语言支持:实现多语言支持,满足不同地区用户的需求
- 无障碍访问:确保应用符合无障碍访问标准,方便行动不便的患者使用
通过对这个个性化用药方案应用的技术解读,我们可以看到 React Native 在跨端开发中的强大能力。该应用不仅实现了完整的用药管理功能,还展示了如何通过 TypeScript、React Hooks 等现代前端技术构建高质量的跨端应用。
真实演示案例代码:
// App.tsx
import React, { useState, useEffect } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Dimensions, Alert, TextInput, Modal } from 'react-native';
// Base64 图标库
const ICONS_BASE64 = {
medicine: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
interaction: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
reminder: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
plan: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};
const { width, height } = Dimensions.get('window');
// 用户类型
type User = {
id: string;
name: string;
age: number;
gender: string;
};
// 药品类型
type Medicine = {
id: string;
name: string;
description: string;
dosage: string;
frequency: string;
time: string;
};
// 用药方案类型
type MedicationPlan = {
id: string;
userId: string;
medicines: Medicine[];
};
// 药品相互作用类型
type DrugInteraction = {
id: string;
medicine1: string;
medicine2: string;
interaction: string;
};
// 漏服补服提醒类型
type MissedDoseReminder = {
id: string;
userId: string;
medicineId: string;
missedTime: string;
rescheduleTime: string;
};
// 个性化用药方案应用组件
const PersonalizedMedicationPlanApp: React.FC = () => {
const [users] = useState<User[]>([
{
id: '1',
name: '李先生',
age: 45,
gender: '男'
},
{
id: '2',
name: '王女士',
age: 32,
gender: '女'
}
]);
const [medicines] = useState<Medicine[]>([
{
id: '1',
name: '阿莫西林',
description: '抗生素类药物,用于治疗细菌感染',
dosage: '500mg',
frequency: '每日三次',
time: '早中晚各一次'
},
{
id: '2',
name: '布洛芬',
description: '解热镇痛药,用于缓解疼痛和发热',
dosage: '200mg',
frequency: '每日两次',
time: '早晚各一次'
}
]);
const [medicationPlans, setMedicationPlans] = useState<MedicationPlan[]>([
{
id: '1',
userId: '1',
medicines: [
{
id: '1',
name: '阿莫西林',
description: '抗生素类药物,用于治疗细菌感染',
dosage: '500mg',
frequency: '每日三次',
time: '早中晚各一次'
}
]
}
]);
const [drugInteractions] = useState<DrugInteraction[]>([
{
id: '1',
medicine1: '阿莫西林',
medicine2: '布洛芬',
interaction: '可能增加胃肠道副作用'
}
]);
const [missedDoseReminders, setMissedDoseReminders] = useState<MissedDoseReminder[]>([
{
id: '1',
userId: '1',
medicineId: '1',
missedTime: '2023-12-01 08:00',
rescheduleTime: '2023-12-01 12:00'
}
]);
const [selectedUser, setSelectedUser] = useState<string | null>(null);
const [selectedMedicine, setSelectedMedicine] = useState<string | null>(null);
const [newMedicine, setNewMedicine] = useState({
name: '',
description: '',
dosage: '',
frequency: '',
time: ''
});
const [isModalVisible, setIsModalVisible] = useState(false);
const [modalContent, setModalContent] = useState('');
// 自动检测药品相互作用
useEffect(() => {
const interval = setInterval(() => {
const randomUser = users[Math.floor(Math.random() * users.length)];
const randomMedicine1 = medicines[Math.floor(Math.random() * medicines.length)];
const randomMedicine2 = medicines[Math.floor(Math.random() * medicines.length)];
const interaction = drugInteractions.find(i =>
(i.medicine1 === randomMedicine1.name && i.medicine2 === randomMedicine2.name) ||
(i.medicine1 === randomMedicine2.name && i.medicine2 === randomMedicine1.name)
);
if (interaction) {
Alert.alert('药品相互作用警告', `检测到${randomMedicine1.name}与${randomMedicine2.name}之间存在相互作用: ${interaction.interaction}`);
}
}, 60000);
return () => clearInterval(interval);
}, [users, medicines, drugInteractions]);
const handleSelectUser = (userId: string) => {
setSelectedUser(userId);
Alert.alert('选择用户', '您已选择该用户进行用药管理');
};
const handleSelectMedicine = (medicineId: string) => {
setSelectedMedicine(medicineId);
Alert.alert('选择药品', '您已选择该药品进行管理');
};
const handleAddMedicine = () => {
if (newMedicine.name && newMedicine.description && newMedicine.dosage && newMedicine.frequency && newMedicine.time && selectedUser) {
const newMed: Medicine = {
id: (medicines.length + 1).toString(),
name: newMedicine.name,
description: newMedicine.description,
dosage: newMedicine.dosage,
frequency: newMedicine.frequency,
time: newMedicine.time
};
setMedicines([...medicines, newMed]);
setMedicationPlans(prevPlans =>
prevPlans.map(plan =>
plan.userId === selectedUser
? { ...plan, medicines: [...plan.medicines, newMed] }
: plan
)
);
setNewMedicine({ name: '', description: '', dosage: '', frequency: '', time: '' });
Alert.alert('添加成功', '新的药品已添加到用药方案中');
} else {
Alert.alert('提示', '请选择用户并填写完整的药品信息');
}
};
const handleViewMedicine = (medicineId: string) => {
const medicine = medicines.find(m => m.id === medicineId);
if (medicine) {
setModalContent(`药品名称: ${medicine.name}\n描述: ${medicine.description}\n剂量: ${medicine.dosage}\n频率: ${medicine.frequency}\n时间: ${medicine.time}`);
setIsModalVisible(true);
}
};
const handleViewPlan = (planId: string) => {
const plan = medicationPlans.find(p => p.id === planId);
if (plan) {
const user = users.find(u => u.id === plan.userId);
const meds = plan.medicines.map(med => `${med.name}: ${med.dosage}, ${med.frequency}, ${med.time}`).join('\n');
setModalContent(`用户: ${user?.name}\n用药方案:\n${meds}`);
setIsModalVisible(true);
}
};
const handleViewInteraction = (interactionId: string) => {
const interaction = drugInteractions.find(i => i.id === interactionId);
if (interaction) {
setModalContent(`药品1: ${interaction.medicine1}\n药品2: ${interaction.medicine2}\n相互作用: ${interaction.interaction}`);
setIsModalVisible(true);
}
};
const handleViewReminder = (reminderId: string) => {
const reminder = missedDoseReminders.find(r => r.id === reminderId);
if (reminder) {
const user = users.find(u => u.id === reminder.userId);
const medicine = medicines.find(m => m.id === reminder.medicineId);
setModalContent(`用户: ${user?.name}\n药品: ${medicine?.name}\n漏服时间: ${reminder.missedTime}\n补服时间: ${reminder.rescheduleTime}`);
setIsModalVisible(true);
}
};
const openModal = (content: string) => {
setModalContent(content);
setIsModalVisible(true);
};
const closeModal = () => {
setIsModalVisible(false);
};
return (
<SafeAreaView style={styles.container}>
{/* 头部 */}
<View style={styles.header}>
<Text style={styles.title}>个性化用药方案</Text>
<Text style={styles.subtitle}>结合药品说明书生成个性化用药方案,支持药品相互作用检测及漏服补服提醒</Text>
</View>
<ScrollView style={styles.content}>
{/* 用户列表 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>用户列表</Text>
{users.map(user => (
<TouchableOpacity
key={user.id}
style={[
styles.card,
selectedUser === user.id && styles.selectedCard
]}
onPress={() => handleSelectUser(user.id)}
>
<Text style={styles.icon}>👤</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>{user.name}</Text>
<Text style={styles.cardDescription}>年龄: {user.age}</Text>
<Text style={styles.cardDescription}>性别: {user.gender}</Text>
</View>
</TouchableOpacity>
))}
</View>
{/* 药品列表 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>药品列表</Text>
{medicines.map(medicine => (
<TouchableOpacity
key={medicine.id}
style={[
styles.card,
selectedMedicine === medicine.id && styles.selectedCard
]}
onPress={() => handleSelectMedicine(medicine.id)}
>
<Text style={styles.icon}>💊</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>{medicine.name}</Text>
<Text style={styles.cardDescription}>描述: {medicine.description}</Text>
<Text style={styles.cardDescription}>剂量: {medicine.dosage}</Text>
<Text style={styles.cardDescription}>频率: {medicine.frequency}</Text>
<Text style={styles.cardDescription}>时间: {medicine.time}</Text>
</View>
<TouchableOpacity
style={styles.viewButton}
onPress={() => handleViewMedicine(medicine.id)}
>
<Text style={styles.viewText}>查看详情</Text>
</TouchableOpacity>
</TouchableOpacity>
))}
</View>
{/* 添加药品 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>添加药品</Text>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
placeholder="药品名称"
value={newMedicine.name}
onChangeText={(text) => setNewMedicine({ ...newMedicine, name: text })}
/>
<TextInput
style={styles.input}
placeholder="药品描述"
value={newMedicine.description}
onChangeText={(text) => setNewMedicine({ ...newMedicine, description: text })}
/>
</View>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
placeholder="剂量"
value={newMedicine.dosage}
onChangeText={(text) => setNewMedicine({ ...newMedicine, dosage: text })}
/>
<TextInput
style={styles.input}
placeholder="频率"
value={newMedicine.frequency}
onChangeText={(text) => setNewMedicine({ ...newMedicine, frequency: text })}
/>
</View>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
placeholder="时间"
value={newMedicine.time}
onChangeText={(text) => setNewMedicine({ ...newMedicine, time: text })}
/>
</View>
<TouchableOpacity
style={styles.addButton}
onPress={handleAddMedicine}
>
<Text style={styles.addText}>添加药品</Text>
</TouchableOpacity>
</View>
{/* 用药方案 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>用药方案</Text>
{medicationPlans.map(plan => (
<TouchableOpacity
key={plan.id}
style={styles.planCard}
onPress={() => handleViewPlan(plan.id)}
>
<Text style={styles.icon}>📋</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>方案ID: {plan.id}</Text>
<Text style={styles.cardDescription}>药品数量: {plan.medicines.length}</Text>
</View>
</TouchableOpacity>
))}
</View>
{/* 药品相互作用 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>药品相互作用</Text>
{drugInteractions.map(interaction => (
<TouchableOpacity
key={interaction.id}
style={styles.interactionCard}
onPress={() => handleViewInteraction(interaction.id)}
>
<Text style={styles.icon}>⚠️</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>相互作用ID: {interaction.id}</Text>
<Text style={styles.cardDescription}>药品1: {interaction.medicine1}</Text>
<Text style={styles.cardDescription}>药品2: {interaction.medicine2}</Text>
<Text style={styles.cardDescription}>相互作用: {interaction.interaction}</Text>
</View>
</TouchableOpacity>
))}
</View>
{/* 漏服补服提醒 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>漏服补服提醒</Text>
{missedDoseReminders.map(reminder => (
<TouchableOpacity
key={reminder.id}
style={styles.reminderCard}
onPress={() => handleViewReminder(reminder.id)}
>
<Text style={styles.icon}>⏰</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>提醒ID: {reminder.id}</Text>
<Text style={styles.cardDescription}>漏服时间: {reminder.missedTime}</Text>
<Text style={styles.cardDescription}>补服时间: {reminder.rescheduleTime}</Text>
</View>
</TouchableOpacity>
))}
</View>
{/* 使用说明 */}
<View style={styles.infoCard}>
<Text style={styles.sectionTitle}>📘 使用说明</Text>
<Text style={styles.infoText}>• 选择用户进行个性化用药管理</Text>
<Text style={styles.infoText}>• 添加药品并生成个性化用药方案</Text>
<Text style={styles.infoText}>• 实时检测药品相互作用</Text>
<Text style={styles.infoText}>• 设置漏服补服提醒</Text>
</View>
{/* 弹框内容 */}
<Modal
animationType="slide"
transparent={true}
visible={isModalVisible}
onRequestClose={closeModal}
>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>详细信息</Text>
<Text style={styles.modalText}>{modalContent}</Text>
<TouchableOpacity
style={styles.closeButton}
onPress={closeModal}
>
<Text style={styles.closeButtonText}>关闭</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f9ff',
},
header: {
flexDirection: 'column',
padding: 16,
backgroundColor: '#ffffff',
borderBottomWidth: 1,
borderBottomColor: '#bae6fd',
},
title: {
fontSize: 20,
fontWeight: 'bold',
color: '#0c4a6e',
marginBottom: 4,
},
subtitle: {
fontSize: 14,
color: '#0284c7',
},
content: {
flex: 1,
marginTop: 12,
},
section: {
backgroundColor: '#ffffff',
marginHorizontal: 16,
marginBottom: 12,
borderRadius: 12,
padding: 16,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
color: '#0c4a6e',
marginBottom: 12,
},
card: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f9ff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
},
selectedCard: {
borderWidth: 2,
borderColor: '#0284c7',
},
planCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f9ff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
},
interactionCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f9ff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
},
reminderCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f9ff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
},
icon: {
fontSize: 28,
marginRight: 12,
},
cardInfo: {
flex: 1,
},
cardTitle: {
fontSize: 16,
fontWeight: '500',
color: '#0c4a6e',
marginBottom: 4,
},
cardDescription: {
fontSize: 14,
color: '#0284c7',
marginBottom: 2,
},
viewButton: {
backgroundColor: '#0284c7',
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 8,
},
viewText: {
color: '#ffffff',
fontSize: 12,
fontWeight: '500',
},
inputRow: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 12,
},
input: {
flex: 1,
backgroundColor: '#f0f9ff',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8,
fontSize: 14,
color: '#0c4a6e',
marginRight: 8,
},
addButton: {
backgroundColor: '#0284c7',
padding: 12,
borderRadius: 8,
alignItems: 'center',
},
addText: {
color: '#ffffff',
fontSize: 14,
fontWeight: '500',
},
infoCard: {
backgroundColor: '#ffffff',
marginHorizontal: 16,
marginBottom: 80,
borderRadius: 12,
padding: 16,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
infoText: {
fontSize: 14,
color: '#64748b',
lineHeight: 20,
marginBottom: 4,
},
modalContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
modalContent: {
width: '80%',
backgroundColor: '#ffffff',
borderRadius: 12,
padding: 20,
elevation: 5,
},
modalTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#0c4a6e',
marginBottom: 12,
textAlign: 'center',
},
modalText: {
fontSize: 14,
color: '#0c4a6e',
lineHeight: 20,
marginBottom: 20,
},
closeButton: {
backgroundColor: '#0284c7',
padding: 10,
borderRadius: 8,
alignItems: 'center',
},
closeButtonText: {
color: '#ffffff',
fontSize: 14,
fontWeight: '500',
},
});
export default PersonalizedMedicationPlanApp;

打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

最后运行效果图如下显示:

本文介绍了基于React Native和鸿蒙系统的个性化用药方案管理应用开发实践。通过React Native的通用API和Hooks体系构建核心功能,实现鸿蒙跨端兼容。采用TypeScript强类型数据模型确保医疗数据精准性,利用React状态管理和药品相互作用检测保障用药安全。UI层通过StyleSheet统一管理样式,适配鸿蒙设备。文章还提出了进一步优化建议,包括使用高性能列表组件、对接鸿蒙原生通知能力及分布式数据同步,以提升医疗应用体验。该方案展现了React Native与鸿蒙生态融合的技术要点,为智慧医疗应用开发提供了参考。
更多推荐


所有评论(0)