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


在互联网医疗领域,在线检查预约正成为提升患者就医便捷性的重要服务模式。今天我们将深入分析一个基于 React Native 开发的互联网医院检查预约应用,探讨其技术实现细节以及在鸿蒙系统上的跨端适配策略。

类组件的复杂性

该应用采用了 React Native 函数式组件架构,结合 TypeScript 提供类型安全保障。从代码结构来看,开发者充分利用了 Hooks 进行状态管理:

const OnlineHospitalTestApp: React.FC = () => {
  const [tests] = useState<Test[]>([...]);
  const [appointments, setAppointments] = useState<Appointment[]>([...]);
  const [selectedTest, setSelectedTest] = useState<string | null>(null);
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [modalContent, setModalContent] = useState('');
  // ...
};

这种设计模式非常适合检查预约场景,因为各个状态之间存在明确的业务逻辑关联,通过局部状态管理即可满足需求。函数式组件的写法不仅代码更简洁,而且在性能上也有优势,避免了类组件的复杂性,同时通过细粒度的状态管理提升了渲染效率。

这种类型定义为代码提供了良好的可维护性

项目使用 TypeScript 定义了清晰的数据模型:

type Test = {
  id: string;
  name: string;
  description: string;
  price: number;
  duration: string;
};

type Appointment = {
  id: string;
  testId: string;
  date: string;
  time: string;
  location: string;
  status: string;
};

这种类型定义为代码提供了良好的可维护性,避免了运行时错误,尤其在跨端开发中,TypeScript 可以帮助开发者在编译时发现潜在问题。

ScrollView` 处理内容滚动

应用采用 Flexbox 布局系统,结合 Dimensions API 实现响应式设计:

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

这种方式确保应用在不同屏幕尺寸的设备上都能良好显示。代码中使用 ScrollView 处理内容滚动,对于检查项目列表和预约信息等长内容非常合适。

从代码中可以看出,开发者采用了 React Native 核心组件,这些组件在 iOS、Android 和鸿蒙系统上都有对应的实现:

  • SafeAreaView 确保内容不被设备刘海或底部安全区域遮挡
  • TouchableOpacity 实现跨平台点击效果
  • Alert 提供统一的弹窗提示
  • Modal 实现跨平台模态框
  • TextInput 处理文本输入

这种"Write Once, Run Anywhere"的理念,使得一套代码可以在多个平台运行,大大提高了开发效率。


检查项目

应用实现了检查项目的选择功能:

const handleSelectTest = (testId: string) => {
  setSelectedTest(testId);
  Alert.alert('选择检查', '您已选择该检查项目');
};

通过 TouchableOpacity 触发选择操作,并通过 Alert 提供即时反馈,提升用户体验。

预约流程

预约创建功能通过表单输入和状态验证实现:

const handleBookAppointment = () => {
  if (selectedTest && newAppointment.date && newAppointment.time && newAppointment.location) {
    const newAppointmentEntry: Appointment = {
      id: (appointments.length + 1).toString(),
      testId: selectedTest,
      date: newAppointment.date,
      time: newAppointment.time,
      location: newAppointment.location,
      status: '待确认'
    };
    setAppointments([...appointments, newAppointmentEntry]);
    setNewAppointment({ date: '', time: '', location: '' });
    Alert.alert('预约成功', '您的预约已提交,请等待确认');
  } else {
    Alert.alert('提示', '请填写完整信息');
  }
};

这种实现方式确保了数据的完整性,同时通过清空输入框和提供操作反馈,优化了用户体验。

预约管理

应用支持预约查看和取消:

const handleViewAppointment = (appointmentId: string) => {
  const appointment = appointments.find(a => a.id === appointmentId);
  if (appointment) {
    const test = tests.find(t => t.id === appointment.testId);
    setModalContent(`检查项目: ${test?.name}\n日期: ${appointment.date}\n时间: ${appointment.time}\n地点: ${appointment.location}\n状态: ${appointment.status}`);
    setIsModalVisible(true);
  }
};

const handleCancelAppointment = (appointmentId: string) => {
  setAppointments(appointments.filter(a => a.id !== appointmentId));
  Alert.alert('取消成功', '您的预约已取消');
};

通过模态框展示详情,避免了页面跳转,保持了操作的连续性。

应用通过样式和图标提供清晰的视觉反馈:

  • 使用卡片式布局展示检查项目和预约信息
  • 通过不同图标区分功能模块
  • 使用 Alert 弹窗确认操作结果
  • 模态框展示详细信息

这种设计使得用户可以直观了解应用状态和操作结果。


在鸿蒙系统上,React Native 核心组件都有对应的实现:

  • View → 鸿蒙 Component
  • Text → 鸿蒙 Text
  • ScrollView → 鸿蒙 ListContainer
  • Modal → 鸿蒙 Dialog
  • TouchableOpacity → 鸿蒙 Button
  • TextInput → 鸿蒙 TextInput

鸿蒙系统对应用性能要求较高,该实现方式有利于性能优化:

  • 函数式组件减少内存占用
  • 多个 useState 钩子实现细粒度状态管理
  • 避免复杂计算和不必要渲染
  • TouchableOpacityButton 减少视图层级

资源加载

代码中使用 Base64 编码图标:

const ICONS_BASE64 = {
  test: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  // ...
};

这种方式减少网络请求,提高加载速度,特别在跨端开发中,避免了不同平台对图片资源处理的差异。


应用采用清晰的模块化结构:

  • 状态管理与 UI 渲染分离
  • 数据结构与业务逻辑分离
  • 样式与组件分离

这种设计使得代码结构清晰,易于维护和扩展。例如添加新检查项目时,只需修改对应数据结构和渲染逻辑。

TypeScript 的使用为代码提供了类型保障,减少了运行时错误。在跨端开发中,类型系统可以帮助开发者发现不同平台间的潜在差异。

代码组织逻辑清晰:

  • 首先定义类型和数据
  • 实现状态管理
  • 编写事件处理函数
  • 最后实现 UI 渲染

通过对互联网医院检查预约应用的分析,我们可以看到 React Native 在跨端开发中的优势:

  • 开发效率高:使用 JavaScript/TypeScript 开发,代码量少,开发周期短
  • 跨平台兼容:一套代码可在 iOS、Android 和鸿蒙系统运行
  • 性能优秀:通过原生组件渲染,性能接近原生应用
  • 生态成熟:拥有丰富的第三方库和工具
  • 用户体验好:可构建与原生应用媲美的界面和交互
  • 功能强大:通过 Hooks 等特性实现复杂业务逻辑

在鸿蒙系统普及的背景下,React Native 作为跨端解决方案具有广阔前景。开发者可以快速构建支持多平台的医疗应用,提高开发效率和代码复用率。

在实际应用中,还可以进一步优化,例如添加支付功能、检查报告查询或医保报销等。这些优化可以在不改变架构的情况下实现,体现了 React Native 的灵活性和可扩展性。


互联网医院检查预约是智慧医疗数字化服务的核心场景之一,聚焦“检查项目选择-预约信息录入-预约下单-预约管理”的全流程自助式检查预约逻辑,既要保证检查项目价格、耗时等核心信息展示的准确性,又需兼顾多端预约流程的一致性与检查地点、时间等关键信息交互的规范性。本文基于这套 React Native 互联网医院检查预约应用代码,从架构设计、核心业务逻辑、鸿蒙跨端适配三个维度,系统解读检查预约场景的跨端开发逻辑与技术要点,重点剖析 React Native 与鸿蒙系统的适配底层逻辑和落地实践方案,尤其针对检查项目选择、预约信息录入、预约管理等核心交互的跨端实现进行深度拆解。

一、应用核心的预约下单(handleBookAppointment)与预约取消(handleCancelAppointment

该互联网医院检查预约应用基于 React Native 函数式组件 + TypeScript 强类型架构构建,核心依赖 React Native 原生基础组件(SafeAreaView、ScrollView、TouchableOpacity、TextInput、Modal 等)与 useState 状态管理,未引入第三方 UI 框架或复杂状态管理库。这种极简架构是检查预约这类“强信息展示、轻实时计算”场景实现鸿蒙跨端的核心优势——轻量意味着适配成本更低,且能最大程度保证多端预约流程逻辑的一致性,尤其适合检查项目列表展示、价格对比、预约信息录入、预约取消等核心逻辑的跨端复用。

从跨端技术底层逻辑来看,React Native 以“JS 桥接层(JS Bridge)”为核心实现跨端能力:前端编写的 JSX 组件与检查预约业务逻辑,通过桥接层映射为不同平台的原生组件,iOS 端映射为 UIKit 体系、Android 端映射为 View 体系,而鸿蒙(HarmonyOS)端则通过 React Native for HarmonyOS 适配层,完成 React Native 组件/API 与鸿蒙 ArkUI 组件/API 的双向映射。该应用的代码结构完全遵循跨端开发规范:无平台专属硬编码、状态管理基于 React 原生 Hooks、样式采用跨端通用的 Flex 布局,从根源上消除了鸿蒙适配的技术壁垒,同时保证检查项目选择、预约下单等核心检查预约流程逻辑在多端的一致性。

值得注意的是,应用核心的预约下单(handleBookAppointment)与预约取消(handleCancelAppointment)逻辑均为纯 JS 数组操作与状态更新实现,无任何平台相关依赖,这是跨端复用的关键——鸿蒙端可通过 JS 引擎直接执行该逻辑,无需适配任何原生能力,保证预约新增/取消规则在多端的完全一致,避免因平台差异导致的预约数据错误。


1. 检查预约场景

应用通过 TypeScript 接口定义了 Test(检查项目)、Appointment(预约)两类核心数据类型,字段设计精准匹配互联网医院检查预约全流程数据需求:

  • Test 涵盖检查项目ID、名称、描述、价格、耗时,价格字段(price)采用 number 类型,耗时字段(duration)采用 string 类型,均为 JS 基础数据类型,在鸿蒙端适配层可直接映射为 ArkTS 的对应类型,避免多端数据类型解析差异导致的检查项目信息展示错误,尤其在“流感检测 150元 30分钟”这类核心检查信息的传递上,保证了跨端的数据准确性;
  • Appointment 采用关联型数据结构设计,通过 testId 关联检查项目,同时包含预约日期、时间、地点、状态,完整覆盖检查预约的核心信息维度,关联 ID 字段为通用字符串格式,在鸿蒙端适配层可直接映射为 ArkTS 的 string 类型,保证预约与检查项目的关联关系跨端一致,避免预约流程中出现“预约-检查项目”匹配错误。

这种强类型+关联型的数据模型设计,在跨端场景下保证了数据结构的一致性——鸿蒙端适配层可直接解析 TypeScript 类型定义,与 ArkTS 中的数据模型形成精准映射,避免多端数据格式不一致导致的检查项目信息展示异常、预约关联关系错乱等核心问题,是检查预约场景跨端落地的基础保障。

2. Hooks 状态管理

应用采用 useState 实现多维度状态管理,核心状态均具备跨端复用的特性:

  • 核心业务状态(tests/appointments)中,tests 为只读设计,适配层自动映射为鸿蒙的 @State 响应式状态,检查项目列表的展示逻辑跨端统一;appointments 支持动态新增(setAppointments)与删除(filter),该更新方法在鸿蒙端会被适配层转换为 ArkTS 的 @State 状态更新逻辑,新增/取消预约后列表可实时渲染,保证多端预约列表展示的一致性;
  • 交互状态(selectedTest)维护选中的检查项目 ID,其更新逻辑为基础字符串赋值操作,鸿蒙端直接执行,选中项的高亮样式(selectedCard)通过条件样式绑定实现,该逻辑为 React 原生语法,鸿蒙端适配层可直接解析,保证选中状态的视觉反馈跨端一致;
  • 表单状态(newAppointment)维护预约录入的日期、时间、地点,采用对象式状态管理,更新逻辑(setNewAppointment({ ...newAppointment, date: text }))使用对象扩展运算符,为 ES6+ 标准语法,鸿蒙端直接执行,表单输入的双向绑定逻辑跨端统一;
  • 弹窗状态(isModalVisible/modalContent)维护弹窗显隐与内容,其更新逻辑为基础状态操作,鸿蒙端适配层会将 Modal 的显示状态映射为 ArkUI 弹窗的显隐状态,弹窗展示预约详情的逻辑跨端统一。

1. 屏幕适配与层级兼容

应用在基础样式之上新增检查项目卡片、预约录入表单、预约卡片专属样式,核心样式设计仍遵循跨端兼容原则,适配鸿蒙系统无明显改造成本,且针对检查预约场景的样式特性做了深度优化:

  • Flex 布局的跨端统一:从检查项目卡片的“图标+信息”、预约录入表单的“横向输入行”,到预约卡片的“图标+预约信息+操作按钮”,全量采用 Flex 布局体系——检查项目卡片使用 flexDirection: 'row' + alignItems: 'center' 横向布局,预约录入表单使用 flexDirection: 'row' + justifyContent: 'space-between' 实现输入框均分排列,预约卡片则通过 Flex 布局实现“信息区+操作按钮区”的横向拆分。Flex 作为 W3C 标准布局方案,在鸿蒙端可被适配层直接解析为 ArkUI 的 Flex 布局,无需重构任何布局逻辑,仅需保证样式属性命名与 React Native 规范一致,尤其在检查项目列表、预约录入表单等核心信息交互区域的布局上,Flex 布局的跨端一致性表现突出;
  • 检查预约专属样式的跨端适配
    • 选中卡片样式(selectedCardborderWidth: 2 + borderColor: '#0284c7')为通用样式属性,鸿蒙端适配层会将边框属性转换为 ArkUI 的 border 相关属性,选中检查项目的高亮边框视觉效果跨端统一,用户可快速识别当前选中的检查类型;
    • 预约录入输入框样式(inputbackgroundColor: '#f0f9ff' + borderRadius: 8 + padding)为通用样式属性,鸿蒙端适配层会将输入框样式转换为 ArkUI 的 TextInput 对应样式,输入框的视觉效果、内边距、圆角跨端统一,保证预约信息录入的交互体验一致;
    • 预约操作按钮(查看详情/取消预约)采用差异化配色(蓝色/红色)与统一的圆角/内边距设计,样式属性均为通用属性,鸿蒙端直接解析,按钮的视觉区分度与点击区域跨端一致,符合用户对“查看”“取消”不同操作的视觉认知;
  • 屏幕适配与层级兼容Dimensions.get('window') 获取设备宽高的 API 在鸿蒙端已完成原生映射,为不同尺寸鸿蒙设备(手机、平板)的自适应布局预留基础;shadow + elevation 的双层阴影设计,鸿蒙系统对 elevation 属性的支持与 Android 端完全兼容,保证检查项目卡片、预约卡片等组件的视觉层级跨端统一;
  • 安全区域适配SafeAreaView 组件在鸿蒙端已适配为 ArkUI 的 SafeArea 组件,保证头部检查预约标题区域在不同鸿蒙设备上的展示完整性,避免标题被刘海屏、全面屏遮挡。

(1)检查项目列表

检查项目列表选择组件是检查预约的核心入口环节,核心适配逻辑如下:

  • 检查项目列表的渲染采用 map 方法遍历 tests 数组,该逻辑为纯 JS 数组操作,鸿蒙端通过 JS 引擎直接执行,列表渲染的顺序与检查项目信息展示的完整性跨端一致,保证检查项目列表展示的准确性;
  • 卡片的条件样式绑定(selectedTest === test.id && styles.selectedCard)为 React 原生语法,鸿蒙端适配层可直接解析样式条件判断逻辑,选中检查项目的高亮边框视觉反馈跨端统一;
  • 选择点击逻辑(handleSelectTest)包含状态更新与弹窗反馈,状态更新为基础字符串赋值,弹窗反馈(Alert.alert)会被适配层转换为鸿蒙的 AlertDialog 组件,提示内容为固定字符串,跨端展示与交互逻辑完全一致;
  • 检查项目价格/耗时展示逻辑(¥{test.price}/耗时: {test.duration})为纯 JS 数值/字符串拼接,鸿蒙端直接执行,价格与耗时展示格式跨端统一,保证检查项目信息的透明化展示。
(2)预约录入与下单组件

预约录入与下单组件是检查预约的核心操作环节,核心适配逻辑如下:

  • 预约录入表单采用 TextInput 组件实现双向绑定,onChangeText 回调中的状态更新逻辑(setNewAppointment({ ...newAppointment, date: text }))使用对象扩展运算符,为 ES6+ 标准语法,鸿蒙端直接执行,表单输入的实时更新逻辑跨端一致;
  • 输入框的横向排列布局(inputRow)采用 flexDirection: 'row' + justifyContent: 'space-between',鸿蒙端适配层直接解析为 ArkUI 的 Flex 布局,输入框的均分排列效果跨端统一;
  • 预约下单逻辑(handleBookAppointment)包含完整的合法性校验:
    1. 空值校验(selectedTest && newAppointment.date && ...)为纯 JS 布尔运算,鸿蒙端直接执行,校验规则跨端一致,保证只有信息完整时才能提交预约;
    2. 新预约对象生成逻辑采用 ES6 对象字面量语法,ID 生成((appointments.length + 1).toString())为纯 JS 数值运算 + 类型转换,鸿蒙端直接执行,预约 ID 生成规则跨端一致;
    3. 预约列表更新(setAppointments([...appointments, newAppointmentEntry]))使用数组扩展运算符,鸿蒙端直接执行,新增预约的规则跨端一致;
    4. 表单重置(setNewAppointment({ date: '', time: '', location: '' }))为基础对象赋值,鸿蒙端直接执行,表单重置逻辑跨端统一;
    5. 反馈提示(Alert.alert)转换为鸿蒙 AlertDialog 组件,提示内容分“成功/失败”两种场景,跨端展示与交互逻辑完全一致。
(3)预约列表与管理组件

预约列表与管理组件是检查预约的核心信息展示与操作环节,核心适配逻辑如下:

  • 预约列表的渲染采用 map 方法遍历 appointments 数组,该逻辑为纯 JS 数组操作,鸿蒙端直接执行,预约列表的展示顺序与信息完整性跨端一致;
  • 预约详情查看逻辑(handleViewAppointment)包含多层数据关联查找:
    1. 预约查找(appointments.find(a => a.id === appointmentId))为纯 JS 数组方法,鸿蒙端直接执行;
    2. 检查项目关联查找(tests.find(t => t.id === appointment.testId))为纯 JS 数组方法,鸿蒙端直接执行,关联规则跨端一致;
    3. 弹窗内容拼接(setModalContent)采用字符串换行拼接,该逻辑为通用 JS 字符串操作,鸿蒙端直接执行,拼接后的预约详情格式(检查项目/日期/时间/地点/状态)跨端统一,保证用户可清晰查看完整的预约信息;
  • 预约取消逻辑(handleCancelAppointment)采用数组 filter 方法实现,为纯 JS 数组操作,鸿蒙端直接执行,取消规则跨端一致,保证点击“取消预约”后对应的预约项能被精准移除;
  • Modal 组件的核心属性(animationType/transparent/visible/onRequestClose)在鸿蒙端会被适配层转换为 ArkUI 的 Dialog 组件对应属性,滑动动画(slide)、透明背景(transparent: true)的逻辑跨端一致,保证预约详情展示体验统一。

1. 预约下单全流程

handleBookAppointment 函数是检查预约的核心业务逻辑,实现了“合法性校验-预约生成-列表更新-表单重置-反馈提示”的全流程预约下单,核心适配逻辑如下:

  • 合法性校验逻辑为纯 JS 布尔运算组合,无任何平台依赖,鸿蒙端直接执行,校验规则(检查项目必选、预约信息必填)跨端一致,保证预约下单的规范性;
  • 新预约对象生成逻辑中,ID 生成((appointments.length + 1).toString())为纯 JS 数值运算 + 类型转换,鸿蒙端直接执行,预约 ID 生成规则跨端一致;
  • 预约列表更新逻辑使用数组扩展运算符,为 ES6+ 标准语法,鸿蒙端直接执行,预约列表的更新规则跨端一致,保证新增预约实时展示;
  • 表单重置逻辑为基础对象赋值,鸿蒙端直接执行,重置规则跨端一致,保证提交预约后表单清空;
  • 反馈提示逻辑使用 Alert.alert API,鸿蒙端适配层转换为 AlertDialog 组件,提示内容分场景设计,跨端展示与交互逻辑完全一致。

2. 预约取消与详情展示逻辑

handleCancelAppointmenthandleViewAppointment 是检查预约的核心操作与信息补充逻辑,核心适配逻辑如下:

  • 预约取消逻辑(handleCancelAppointment)采用数组 filter 方法过滤掉目标预约项,为纯 JS 数组操作,鸿蒙端直接执行,取消规则跨端一致,保证预约取消操作的准确性;
  • 预约详情查看逻辑(handleViewAppointment)包含多层数据关联查找,所有查找逻辑均为纯 JS 数组方法,鸿蒙端直接执行,关联规则跨端一致,保证预约与对应的检查项目信息精准匹配;
  • 弹窗内容拼接逻辑为通用 JS 字符串操作,鸿蒙端直接执行,拼接后的预约详情格式跨端统一,保证信息展示的完整性与可读性。

应用使用的核心 API 均为 React Native 跨端兼容 API,在鸿蒙端可无缝适配:

  • 数组 API:map/find/filter/扩展运算符等数组方法为 JS 原生 API,鸿蒙端通过 JS 引擎直接执行,无需适配,保证检查项目/预约列表的渲染、查找、更新、删除等核心逻辑的跨端一致性;
  • 字符串 API:字符串拼接/换行符(\n)等操作为 JS 原生 API,鸿蒙端直接执行,保证弹窗内容拼接等核心逻辑的跨端一致性;
  • 表单 API:TextInput 组件的 onChangeText/value 属性在鸿蒙端已完成适配,双向绑定逻辑跨端一致,保证预约信息录入的交互体验统一;
  • 弹窗 API:Alert.alert/Modal 已被适配层封装为鸿蒙的 AlertDialog/Dialog 组件,交互逻辑完全复用,在检查项目选择反馈、预约下单/取消反馈、预约详情展示等核心场景中,弹窗的展示与操作逻辑多端统一;
  • 样式 API:StyleSheet.create 封装的样式规则,适配层转换为 ArkUI 的样式对象,新增的选中卡片边框、预约输入框、操作按钮样式属性均为通用属性,无需修改即可适配鸿蒙。

该互联网医院检查预约应用作为智慧医疗数字化服务核心模块,适配鸿蒙系统的成本极低,核心适配思路与技术要点如下:

应用核心的预约下单、取消、数据关联查找、合法性校验等逻辑均为纯 JS 实现,无任何平台相关依赖,这是跨端复用的最大优势——鸿蒙端可通过 JS 引擎直接执行该逻辑,无需适配任何原生能力。在生产环境中扩展预约支付、检查报告查询、电子发票等逻辑时,新增规则仍为纯 JS 逻辑,鸿蒙端可直接复用,仅需保证规则逻辑的通用性,无需考虑平台差异,这也是检查预约场景跨端开发的核心优势。

该应用当前的列表渲染采用基础 map 方法,在生产环境中若检查项目/预约数据量较大(如超过100个检查项目、200条预约),可替换为 React Native 的 FlatList 高性能列表组件——FlatList 在鸿蒙端已完成深度适配,支持虚拟化列表渲染,其核心属性(data/renderItem/keyExtractor)与 React Native 端完全一致,仅需少量调整即可适配鸿蒙端的性能优化策略,保证列表的滚动性能,尤其适合长期检查预约服务产生的海量预约数据展示场景。

3. 检查预约样式

鸿蒙系统有自身的设计规范,在适配时可通过条件编译实现差异化样式,既保证遵循鸿蒙设计规范,又能最大程度复用现有代码:

// 鸿蒙端检查预约样式差异化适配示例
import { Platform } from 'react-native';
const isHarmonyOS = Platform.OS === 'harmony';

const adaptiveStyles = {
  card: {
    ...styles.card,
    backgroundColor: isHarmonyOS ? '#e0f7fa' : '#f0f9ff',
    borderRadius: isHarmonyOS ? 14 : 12,
  },
  selectedCard: {
    ...styles.selectedCard,
    borderColor: isHarmonyOS ? '#0369a1' : '#0284c7',
  },
  input: {
    ...styles.input,
    backgroundColor: isHarmonyOS ? '#e0f7fa' : '#f0f9ff',
    borderRadius: isHarmonyOS ? 10 : 8,
  },
  bookButton: {
    ...styles.bookButton,
    backgroundColor: isHarmonyOS ? '#0369a1' : '#0284c7',
    borderRadius: isHarmonyOS ? 10 : 8,
  },
  cancelButton: {
    ...styles.cancelButton,
    backgroundColor: isHarmonyOS ? '#dc2626' : '#ef4444',
    borderRadius: isHarmonyOS ? 10 : 8,
  }
};

这种轻量级的差异化适配,既能保证符合鸿蒙的设计规范,又能保留现有代码的完整性,尤其在检查项目卡片、预约输入框、预约操作按钮等核心检查预约交互组件的样式适配中,效果显著。

该 React Native 互联网医院检查预约应用实现了检查项目选择、预约信息录入、预约下单、预约取消、预约详情查看等核心智慧医疗数字化服务功能,代码结构符合跨端开发规范,可低成本适配鸿蒙系统。针对生产环境落地,可做以下优化:

  1. 预约时间合法性校验:新增预约日期/时间的格式校验与合理性校验(如不能选择过去的时间、检查机构营业时间校验),校验逻辑为纯 JS 正则表达式与日期处理实现,鸿蒙端直接执行,提升预约信息录入的准确性;
  2. 检查地点自动解析:通过 React Native 原生模块封装鸿蒙的位置服务 API,实现检查地点的自动解析与定位,核心预约逻辑可完全复用现有代码,仅需对接鸿蒙的位置原生 API,提升地址录入的便捷性;
  3. 数据持久化与同步:引入 AsyncStorage(或鸿蒙原生 Preferences)实现检查项目/预约数据的本地加密存储,同时对接医疗云平台接口实现数据云端同步,鸿蒙端兼容主流存储方案,可直接复用数据处理逻辑,保证用户预约数据的跨设备同步;
  4. 检查报告对接:新增检查报告查询入口,报告查询逻辑为纯 JS 接口请求实现,鸿蒙端直接执行,完善检查预约的服务闭环;
  5. 支付流程扩展:新增预约支付功能,支付逻辑通过封装鸿蒙的支付原生模块实现,核心预约逻辑无需修改,仅需对接鸿蒙的支付 API,完成检查预约的交易闭环。

真实演示案例代码:





// App.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Dimensions, Alert, TextInput, Modal } from 'react-native';

// Base64 图标库
const ICONS_BASE64 = {
  test: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  calendar: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  location: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  info: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};

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

// 检查项目类型
type Test = {
  id: string;
  name: string;
  description: string;
  price: number;
  duration: string;
};

// 预约类型
type Appointment = {
  id: string;
  testId: string;
  date: string;
  time: string;
  location: string;
  status: string;
};

// 互联网医院检查预约应用组件
const OnlineHospitalTestApp: React.FC = () => {
  const [tests] = useState<Test[]>([
    {
      id: '1',
      name: '流感检测',
      description: '快速检测是否感染流感病毒',
      price: 150,
      duration: '30分钟'
    },
    {
      id: '2',
      name: '血常规',
      description: '全面了解血液健康状况',
      price: 80,
      duration: '20分钟'
    }
  ]);

  const [appointments, setAppointments] = useState<Appointment[]>([
    {
      id: '1',
      testId: '1',
      date: '2023-12-10',
      time: '10:00',
      location: '北京市朝阳区建国路1号',
      status: '待确认'
    }
  ]);

  const [selectedTest, setSelectedTest] = useState<string | null>(null);
  const [newAppointment, setNewAppointment] = useState({
    date: '',
    time: '',
    location: ''
  });

  const [isModalVisible, setIsModalVisible] = useState(false);
  const [modalContent, setModalContent] = useState('');

  const handleSelectTest = (testId: string) => {
    setSelectedTest(testId);
    Alert.alert('选择检查', '您已选择该检查项目');
  };

  const handleBookAppointment = () => {
    if (selectedTest && newAppointment.date && newAppointment.time && newAppointment.location) {
      const newAppointmentEntry: Appointment = {
        id: (appointments.length + 1).toString(),
        testId: selectedTest,
        date: newAppointment.date,
        time: newAppointment.time,
        location: newAppointment.location,
        status: '待确认'
      };
      setAppointments([...appointments, newAppointmentEntry]);
      setNewAppointment({ date: '', time: '', location: '' });
      Alert.alert('预约成功', '您的预约已提交,请等待确认');
    } else {
      Alert.alert('提示', '请填写完整的预约信息');
    }
  };

  const handleViewAppointment = (appointmentId: string) => {
    const appointment = appointments.find(a => a.id === appointmentId);
    if (appointment) {
      const test = tests.find(t => t.id === appointment.testId);
      setModalContent(`检查项目: ${test?.name}\n日期: ${appointment.date}\n时间: ${appointment.time}\n地点: ${appointment.location}\n状态: ${appointment.status}`);
      setIsModalVisible(true);
    }
  };

  const handleCancelAppointment = (appointmentId: string) => {
    setAppointments(appointments.filter(a => a.id !== appointmentId));
    Alert.alert('取消成功', '您的预约已取消');
  };

  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>
          {tests.map(test => (
            <TouchableOpacity 
              key={test.id}
              style={[
                styles.card,
                selectedTest === test.id && styles.selectedCard
              ]}
              onPress={() => handleSelectTest(test.id)}
            >
              <Text style={styles.icon}>🧪</Text>
              <View style={styles.cardInfo}>
                <Text style={styles.cardTitle}>{test.name}</Text>
                <Text style={styles.cardDescription}>{test.description}</Text>
                <Text style={styles.cardDescription}>价格: ¥{test.price}</Text>
                <Text style={styles.cardDescription}>耗时: {test.duration}</Text>
              </View>
            </TouchableOpacity>
          ))}
        </View>

        {/* 预约信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>预约信息</Text>
          <View style={styles.inputRow}>
            <TextInput
              style={styles.input}
              placeholder="预约日期 (YYYY-MM-DD)"
              value={newAppointment.date}
              onChangeText={(text) => setNewAppointment({ ...newAppointment, date: text })}
            />
            <TextInput
              style={styles.input}
              placeholder="预约时间 (HH:MM)"
              value={newAppointment.time}
              onChangeText={(text) => setNewAppointment({ ...newAppointment, time: text })}
            />
          </View>
          <View style={styles.inputRow}>
            <TextInput
              style={styles.input}
              placeholder="检查地点"
              value={newAppointment.location}
              onChangeText={(text) => setNewAppointment({ ...newAppointment, location: text })}
            />
          </View>
          <TouchableOpacity 
            style={styles.bookButton}
            onPress={handleBookAppointment}
          >
            <Text style={styles.bookText}>预约检查</Text>
          </TouchableOpacity>
        </View>

        {/* 预约列表 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>预约列表</Text>
          {appointments.map(appointment => (
            <View key={appointment.id} style={styles.appointmentCard}>
              <Text style={styles.icon}>📅</Text>
              <View style={styles.cardInfo}>
                <Text style={styles.cardTitle}>预约ID: {appointment.id}</Text>
                <Text style={styles.cardDescription}>日期: {appointment.date}</Text>
                <Text style={styles.cardDescription}>时间: {appointment.time}</Text>
                <Text style={styles.cardDescription}>地点: {appointment.location}</Text>
                <Text style={styles.cardDescription}>状态: {appointment.status}</Text>
              </View>
              <TouchableOpacity 
                style={styles.viewButton}
                onPress={() => handleViewAppointment(appointment.id)}
              >
                <Text style={styles.viewText}>查看详情</Text>
              </TouchableOpacity>
              <TouchableOpacity 
                style={styles.cancelButton}
                onPress={() => handleCancelAppointment(appointment.id)}
              >
                <Text style={styles.cancelText}>取消预约</Text>
              </TouchableOpacity>
            </View>
          ))}
        </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',
  },
  icon: {
    fontSize: 28,
    marginRight: 12,
  },
  cardInfo: {
    flex: 1,
  },
  cardTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#0c4a6e',
    marginBottom: 4,
  },
  cardDescription: {
    fontSize: 14,
    color: '#0284c7',
    marginBottom: 2,
  },
  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,
  },
  bookButton: {
    backgroundColor: '#0284c7',
    padding: 12,
    borderRadius: 8,
    alignItems: 'center',
  },
  bookText: {
    color: '#ffffff',
    fontSize: 14,
    fontWeight: '500',
  },
  appointmentCard: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#f0f9ff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 12,
  },
  viewButton: {
    backgroundColor: '#0284c7',
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 8,
    marginRight: 8,
  },
  viewText: {
    color: '#ffffff',
    fontSize: 12,
    fontWeight: '500',
  },
  cancelButton: {
    backgroundColor: '#ef4444',
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 8,
  },
  cancelText: {
    color: '#ffffff',
    fontSize: 12,
    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 OnlineHospitalTestApp;


请添加图片描述


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述
本文分析了一个基于React Native开发的互联网医院检查预约应用,重点探讨其技术实现和鸿蒙跨端适配策略。应用采用函数式组件和TypeScript强类型架构,通过Hooks实现状态管理,确保代码简洁高效。核心功能包括检查项目选择、预约创建和管理,采用Flexbox布局和响应式设计适配多端。文章详细解析了React Native组件在鸿蒙系统的映射关系,如View→Component、Text→Text等,并指出TypeScript类型系统在跨端开发中的优势。该实现展示了React Native"一次编写,多端运行"的特点,在保持性能接近原生应用的同时,提高了开发效率和代码复用率,为智慧医疗数字化服务提供了可靠的技术方案。

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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐