欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。


个性化用药管理是智慧医疗的核心场景之一,这类应用需要兼顾用药数据精准性、药品相互作用检测、用药提醒时效性等关键能力,而鸿蒙系统的分布式全场景特性,为医疗应用跨端部署和数据同步提供了天然优势。本文将深度拆解基于React Native开发的个性化用药方案应用代码,从医疗数据模型设计、药品相互作用自动检测逻辑、用药方案管理到鸿蒙系统跨端兼容的核心技术要点,全方位剖析医疗用药类跨端应用的开发范式与最佳实践。

应用架构设计

这款个性化用药方案应用聚焦于用药方案定制、药品相互作用检测、漏服补服提醒等核心医疗功能,涵盖用户档案管理、药品信息维护、用药方案生成、风险检测、提醒管理等完整业务链路。从架构层面来看,应用完全遵循React Native的组件化设计思想,以TypeScript构建强类型的医疗用药数据模型,这种设计既保证了用药数据的精准性和交互逻辑的严谨性,也为鸿蒙系统的跨端兼容奠定了核心基础。

从跨端适配的底层逻辑分析,代码中未引入任何平台专属API(如iOS的HealthKit、Android的AlarmManager或鸿蒙的NotificationKit),所有核心功能均基于React Native的通用核心组件(SafeAreaView、View、Text、TextInput、Modal等)和基础API(Dimensions、Alert、TouchableOpacity)构建。在鸿蒙系统中,这些通用组件会被React Native for HarmonyOS框架无缝转换为ArkUI原生组件——例如TextInput映射为鸿蒙的TextInput组件、Modal映射为鸿蒙的Dialog组件、TouchableOpacity适配为鸿蒙的Button组件,Alert则调用鸿蒙的原生弹窗能力,从而保证UI渲染和交互逻辑在鸿蒙设备上的一致性。这种“通用抽象层+平台适配层”的架构设计,规避了因平台医疗能力差异导致的代码碎片化,同时满足用药管理应用对跨端数据一致性和风险检测准确性的严苛要求。

强类型医疗数据模型:

用药管理的核心是数据的精准性和完整性,代码中通过多层级的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[]; // 多药品集合,适配组合用药场景
};

// 药品相互作用与提醒模型(风险管控核心)
type DrugInteraction = {
  id: string;
  medicine1: string;
  medicine2: string;
  interaction: string;  // 相互作用描述,保障用药安全
};
type MissedDoseReminder = {
  id: string;
  userId: string;
  medicineId: string;
  missedTime: string;   // 漏服时间(字符串型,兼容时间格式跨端一致性)
  rescheduleTime: string; // 补服时间
};

这些类型定义严格约束了用药数据的格式和类型,在鸿蒙系统中,React Native的TypeScript编译器会对JS层与鸿蒙ArkTS层之间的数据交互进行类型校验——例如药品剂量、用药频率等核心参数在跨端传递时,会被强制校验为对应类型,避免了因鸿蒙ArkTS的静态类型特性与JavaScript动态类型特性不兼容导致的用药信息展示错误。值得注意的是,用药相关时间、剂量等字段采用字符串类型存储,这种设计兼顾了医疗数据的可读性和跨端兼容性,避免了不同平台对数值格式解析差异导致的用药信息失真,符合医疗数据展示的行业规范。


应用的核心业务逻辑基于React Hooks(useState、useEffect)实现,这种轻量级的状态管理方式完美适配React Native的跨端生命周期模型,同时与鸿蒙系统的组件生命周期形成深度映射,尤其适配了药品相互作用自动检测这类周期性任务的需求。

核心状态

// 基础用药数据状态(不可变初始化)
const [users] = useState<User[]>([/* 初始化用户档案 */]);
const [medicines] = useState<Medicine[]>([/* 初始化药品信息 */]);
const [medicationPlans, setMedicationPlans] = useState<MedicationPlan[]>([/* 初始化用药方案 */]);
const [drugInteractions] = useState<DrugInteraction[]>([/* 初始化药品相互作用数据 */]);

// 交互与表单状态
const [selectedUser, setSelectedUser] = useState<string | null>(null);
const [selectedMedicine, setSelectedMedicine] = useState<string | null>(null);
const [newMedicine, setNewMedicine] = useState({/* 药品表单初始值 */});

useState负责管理组件内部的状态数据,其不可变的状态更新机制(如setMedicationPlans(prevPlans => prevPlans.map(...)))保证了用药数据的一致性——每次添加新药品到用药方案时,都会创建新的数组副本,而非修改原数组,这种设计在鸿蒙系统中能够避免因引用类型数据共享导致的状态混乱,尤其适配了鸿蒙分布式数据管理中“数据副本一致性”的核心要求。而useEffect则承担了跨端生命周期管理的核心职责,代码中通过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]);

这段代码在鸿蒙系统中稳定运行的核心原因在于:setInterval/clearInterval是React Native封装的通用定时器API,已适配鸿蒙的任务调度机制,60秒一次的检测频率既满足用药风险管控的时效性要求,又不会过度占用鸿蒙设备资源;useEffect的返回清理函数则对应鸿蒙组件的onDestroy生命周期,确保定时器在组件卸载时被正确销毁,避免鸿蒙系统中的内存泄漏问题——这对需要长期运行、实时检测用药风险的医疗应用尤为重要。同时,药品相互作用的查找逻辑采用标准化的数组find方法,在鸿蒙设备上能够保证检索结果的一致性,避免了不同平台数组方法实现差异导致的风险检测遗漏。


应用的UI层完全基于React Native的核心组件构建,样式通过StyleSheet.create统一管理,这种设计既保证了UI在鸿蒙系统中的无缝适配,又兼顾了医疗用药应用对数据展示清晰性、操作安全性的特殊要求。

样式系统

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f0f9ff', // 医疗类应用专属浅蓝主题,适配鸿蒙视觉规范
  },
  section: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    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',
    marginRight: 8,
  },
  // 按钮、卡片、弹窗等组件样式定义
});

StyleSheet将CSS样式抽象为跨平台的样式对象,在鸿蒙系统中,flex布局、padding/margin、borderRadius等核心样式属性会被精准转换为ArkUI的布局属性(如flexDirection、paddingLeft、borderRadius);代码中通过Dimensions.get('window')获取屏幕尺寸:

const { width, height } = Dimensions.get('window');

该API在鸿蒙系统中能够准确获取设备的屏幕像素尺寸,避免了直接使用鸿蒙原生API(如getWindowSize)导致的代码碎片化,保证了不同屏幕尺寸鸿蒙设备(手机、平板、智慧屏)上的布局一致性——尤其适配了用药管理应用在鸿蒙多形态设备上的展示需求,比如在鸿蒙平板上展示完整的用药方案详情,在手机上展示简化的用药提醒。

交互组件

核心交互逻辑基于TouchableOpacity组件实现,该组件在鸿蒙系统中会被渲染为具备点击反馈的原生按钮组件,保证了跨端交互体验的统一,同时其选中态的边框高亮样式(selectedCard)能够清晰标识当前选择的用户/药品,符合医疗用药应用的操作指引要求:

<TouchableOpacity 
  style={[styles.card, selectedUser === user.id && styles.selectedCard]}
  onPress={() => handleSelectUser(user.id)}
>
  {/* 用户档案信息展示 */}
</TouchableOpacity>

Modal组件通过animationType="slide"实现滑动弹窗效果,在鸿蒙系统中适配为原生的滑动模态框,用于展示药品详细信息、用药方案、药品相互作用风险提示,既保证了医疗数据展示的完整性,又符合鸿蒙系统的交互规范。TextInput组件采用多行多列的布局方式,适配药品名称、剂量、频率等多维度信息的录入,在鸿蒙设备上能够保证输入框的响应速度和输入体验,避免因平台输入组件差异导致的信息录入错误。

当前代码已具备基础的鸿蒙兼容能力,在生产环境中可针对鸿蒙系统的特性和用药管理应用的特殊需求进行以下优化,进一步提升应用体验:

  1. 高性能列表渲染优化:当前用药方案、药品相互作用列表采用ScrollView + map的方式渲染,在鸿蒙系统中面对大量历史用药数据时可能出现卡顿。可替换为React Native的FlatList组件,该组件在鸿蒙系统中会适配ArkUI的List组件,实现按需渲染和组件复用,同时通过getItemLayout优化列表滚动性能,尤其适合展示用户长期的用药记录和提醒信息。

  2. 鸿蒙原生提醒能力集成:若需调用鸿蒙的原生提醒能力(如系统级用药提醒、分布式通知),可通过React Native的Native Module机制封装鸿蒙的NotificationKit和AlarmManager API,构建JS与ArkTS的通信桥梁——例如将应用中的漏服补服提醒对接鸿蒙的系统通知,实现跨鸿蒙设备的用药提醒同步,在保留跨端代码架构的同时,充分利用鸿蒙系统的原生提醒能力。

  3. 分布式用药数据同步:鸿蒙系统的核心特性是分布式能力,可基于React Native的跨端通信机制,实现用药数据在多鸿蒙设备(手机、智能手表、家庭智慧屏)之间的分布式同步——例如用户手机上的用药方案,可同步到鸿蒙智能手表的用药提醒模块,实现多设备联动的用药管理,提升用药依从性。

这款基于React Native开发的个性化用药方案应用,通过TypeScript强类型约束、React Hooks状态管理、通用UI组件与样式设计,构建了具备完整鸿蒙跨端兼容能力的医疗用药类应用架构。核心技术要点可总结为:

  • 采用通用API+组件构建核心用药管理业务逻辑,规避平台专属代码,是实现鸿蒙兼容的基础,同时保证了用药数据展示和风险检测的跨端一致性;
  • 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 鸿蒙跨端开发中,该应用体现了以下关键技术点:

  1. 组件兼容性:使用 React Native 核心组件(如 View、Text、TouchableOpacity、ScrollView、Modal 等),确保在鸿蒙系统上的兼容性
  2. 资源管理:通过 Base64 编码的图标资源,避免了不同平台资源格式的差异,提高了跨端部署的一致性
  3. 尺寸适配:使用 Dimensions API 获取屏幕尺寸,实现响应式布局,适应不同设备屏幕
  4. 状态管理:采用 React Hooks 进行状态管理,保持跨平台代码一致性
  5. 类型安全:TypeScript 类型定义确保了数据结构在不同平台间的一致性
  6. API 调用:使用 React Native 统一的 API 调用方式,如 Alert 组件,确保在鸿蒙平台上的正确显示

1. 药品管理功能

应用实现了药品的添加和管理功能,通过表单输入收集药品信息,并将其添加到用户的用药方案中:

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('提示', '请选择用户并填写完整的药品信息');
  }
};

2. 药品信息查看功能

应用提供了药品详细信息的查看功能,通过模态框展示药品的各项属性:

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 设计遵循了现代移动应用的设计原则,使用了以下组件和交互模式:

  • 滚动视图:通过 ScrollView 实现内容的垂直滚动,适应不同长度的药品列表和用药方案
  • 卡片布局:使用 TouchableOpacity 和 View 组合实现卡片式列表项,提供清晰的视觉层次
  • 模态框:通过 Modal 组件展示药品详情和用药方案信息
  • 交互反馈:使用 Alert 组件提供操作反馈和药品相互作用警告
  • 响应式设计:根据屏幕尺寸动态调整布局,确保在不同设备上的良好显示效果

  1. 跨端架构:基于 React Native 构建,实现了一次编码多平台运行的目标,特别关注了鸿蒙平台的适配
  2. 类型安全:全面使用 TypeScript 类型定义,提高代码质量和可维护性,确保医疗数据的准确性
  3. 药品相互作用检测:实现了自动检测药品相互作用的功能,为患者用药安全提供了技术保障
  4. 个性化用药方案:根据用户信息和药品特性,为每个用户提供个性化的用药方案
  5. 漏服提醒管理:通过漏服补服提醒功能,提高患者用药依从性
  6. 模块化设计:通过清晰的类型定义和函数划分,实现了代码的模块化,提高了可维护性
  7. 实时数据反馈:通过即时的 Alert 反馈,增强用户操作体验
  8. 数据结构设计:通过嵌套的数据结构,如用药方案包含药品,实现了复杂医疗数据的有效组织

在实际应用中,还可以考虑以下性能优化策略:

  1. 状态管理优化:对于大型应用,可以考虑使用 Redux 或 Context API 进行全局状态管理,提高状态更新的效率
  2. 组件拆分:将大型组件拆分为更小的可复用组件,提高渲染性能和代码可维护性
  3. 数据缓存:对药品信息和用户数据进行本地缓存,减少重复计算和网络请求
  4. 动画性能:使用 React Native 的 Animated API 实现流畅的过渡动画,提升用户体验
  5. 内存管理:确保及时清理不再使用的状态和事件监听器,避免内存泄漏
  6. 网络优化:对于实际应用中的远程数据同步,实现合理的网络请求策略,如批量上传、增量同步等
  7. 计算优化:对于药品相互作用检测等频繁操作,可以考虑使用 memoization 技术缓存计算结果
  8. 列表优化:对于长列表,使用 FlatList 组件替代 ScrollView,提高渲染性能

在开发过程中,可能面临的技术挑战及解决方案:

  1. 鸿蒙平台适配:通过使用 React Native 核心组件和统一的 API 调用方式,确保应用在鸿蒙平台上的兼容性
  2. 药品相互作用数据更新:建立药品相互作用数据库的定期更新机制,确保数据的准确性和时效性
  3. 实时提醒功能:结合本地推送通知和后台任务,实现准确的用药提醒功能
  4. 数据安全:实现医疗数据的加密存储和传输,保护患者隐私
  5. 离线功能:实现基本的离线操作能力,确保在网络不稳定情况下的正常使用
  6. 性能优化:针对不同设备性能差异,实现自适应的性能优化策略,确保在中低端设备上的流畅运行

通过对这个个性化用药方案应用的技术解读,我们可以看到 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开发的个性化用药管理应用,该应用充分利用鸿蒙系统的跨平台特性实现医疗场景下的用药方案管理。文章详细解析了应用架构设计,采用TypeScript构建强类型医疗数据模型,确保用药数据的精准性和跨端一致性。核心功能包括药品相互作用检测、用药提醒等,通过React Hooks实现状态管理,适配鸿蒙设备生命周期。UI层完全基于React Native核心组件,样式系统兼顾医疗应用的数据清晰性和操作安全性。该设计模式为医疗类跨端应用开发提供了实践参考,有效解决了不同平台间的兼容性问题。

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐