React Native × 鸿蒙跨端技术解读:订单详情页的组件与系统能力桥接

这段代码实现了一个“订单详情”页面:以卡片组件组织订单状态、商品清单、收货与订单信息、操作按钮、流程指示器和 FAQ,交互以 Alert 作为占位。它在 iOS/Android 走 React Native 标准组件栈;落地到鸿蒙(OpenHarmony)时,需要通过 RN 的鸿蒙适配层将导航、弹窗、拨号与物流跳转等系统能力桥接到 ArkUI 与系统服务,确保一致的交互体验与能力表现。

[app.tsx](file:///Users/david/workspace/demo/book/app.tsx)

结构概览与数据来源

页面主数据以 useState 固定一个 order 对象(订单号、状态、时间、总金额、支付/物流/收货信息与商品列表),符合原型阶段的静态演示。视图由 ScrollView 承载多个卡片区块,底部导航保持分区视觉语言。对生产环境,建议把 order 来源替换为异步数据(服务端 API)并引入错误回滚与缓存,统一时间/货币格式与本地化。

const [order] = useState({
  id: 'ORD-20230615-001',
  status: '配送中',
  date: '2023-06-15 14:30',
  total: 345.60,
  paymentMethod: '微信支付',
  shippingAddress: '...',
  receiver: '张三',
  phone: '138****8888',
  items: [
    { id: '1', name: '运动跑步鞋', price: 299.00, quantity: 1, image: '👟' },
    { id: '2', name: '运动水壶', price: 46.60, quantity: 1, image: '💧' },
  ],
  shippingMethod: '顺丰快递',
  trackingNumber: 'SF1234567890',
  notes: '请放置在门口',
});

状态标签组件:OrderStatus 的语义映射

OrderStatus 接收一个状态字符串并派生颜色,呈现为可视化标签。映射以 switch 实现,语义色覆盖“已下单/已支付/配送中/已完成/已取消”的常见阶段。为提升鲁棒性,生产建议改为“枚举类型 + 映射表”,避免文案变更引发错误,并提取纯函数统一供流程指示器等组件复用。

const OrderStatus = ({ status }: { status: string }) => {
  const getStatusColor = () => {
    switch (status) {
      case '已下单': return '#f59e0b';
      case '已支付': return '#3b82f6';
      case '配送中': return '#f59e0b';
      case '已完成': return '#10b981';
      case '已取消': return '#ef4444';
      default: return '#94a3b8';
    }
  };
  return (
    <View>
      <Text style={{ color: getStatusColor() }}>{status}</Text>
    </View>
  );
};

跨端注意:视觉语义应与流程指示器色板保持一致;当引入主题或深色模式时,建议统一通过主题系统派生颜色。

商品卡片组件:OrderItem 的金额与数量计算

OrderItem 聚合商品图标、名称、单价 × 数量与行总价,行总价以 price * quantity 计算并格式化为两位小数。该组件保持展示职责纯粹,并不处理折扣/税费等业务规则;生产需要统一货币格式器(包含千分位、本地化符号与货币代码),并将参与总计的规则统一封装在服务层,确保与支付结算一致。

const OrderItem = ({ name, price, quantity, image }: { name: string; price: number; quantity: number; image: string }) => {
  return (
    <View>
      <View><Text>{image}</Text></View>
      <View>
        <Text>{name}</Text>
        <Text>¥{price.toFixed(2)} × {quantity}</Text>
      </View>
      <Text>¥{(price * quantity).toFixed(2)}</Text>
    </View>
  );
};

图标当前以 emoji 占位,跨端在不同系统字体下可能出现对齐与渲染差异;生产建议统一矢量/字体图标栈,并在鸿蒙端通过 ArkUI 的图形能力映射,保证像素与基线一致。

详情行组件:OrderDetail 的标签/值结构

OrderDetail 以“标签/值”组成一行,支持 isImportant 提升权重;该结构用于“支付方式、配送方式、物流单号、订单备注”等通用信息。为兼容多语言与复杂格式(例如电话、地址),建议对值进行类型化,并在展示层按类型渲染(tel → 拨号、addr → 地图定位),使交互更直达。

const OrderDetail = ({ label, value, isImportant = false }: { label: string; value: string; isImportant?: boolean }) => {
  return (
    <View>
      <Text>{label}</Text>
      <Text style={isImportant ? /* 加重 */ {} : {}}>{value}</Text>
    </View>
  );
};

页面交互:系统能力的占位桥接

三类操作以 Alert 占位:

  • 联系客服:提示“拨打客服电话”。生产中应桥接系统拨号功能(iOS 使用 URL scheme tel://,Android 使用 Intent,鸿蒙端通过 Ability 的拨号接口),并在权限未授权时引导用户开启。
  • 查看物流:提示物流单号并“跳转物流详情页面”。生产应使用深度链接或 WebView 打开快递查询页,确保三端统一的跳转与返回行为(鸿蒙端通过 Ability/Router 接口)。
  • 取消订单:二次确认后提示取消成功。生产需调用服务端 API 并进行错误处理与状态刷新。
const handleContactSupport = () => { Alert.alert('联系客服', '拨打客服电话: 400-123-4567', [ /* ... */ ]); };
const handleTrackOrder = () => { Alert.alert('物流跟踪', `物流单号: ${order.trackingNumber}\n...`, [ /* ... */ ]); };
const handleCancelOrder = () => { Alert.alert('取消订单', '确定要取消此订单吗?', [ /* ... */ ]); };

Alert 的视觉与按钮布局由平台决定;鸿蒙端需确保桥接到规范的系统对话框。如果希望统一视觉与行为,建议使用 RN 的 Modal 自绘弹窗,注入一致的动效与可访问性焦点管理。

订单流程指示器:阶段化进度的可视表达

流程指示器通过“节点圆 + 连线”的组合,按“已下单/已支付/配送中/已完成”呈现阶段化状态。当前逻辑静态,生产建议:

  • 把阶段集合与颜色映射抽象为常量或配置表;
  • 根据 OrderStatus 的当前状态,动态高亮已完成阶段与当前阶段;
  • 对“已取消/异常”提供分支流程或中断提示。

这能让流程指示与状态标签保持一致语义,降低认知负担。

FAQ 交互:轻量问答占位

FAQ 列表通过 TouchableOpacity + Alert 实现轻量问答;生产场景可替换为知识库页或客服入口(在线聊天、机器人),并记录点击事件用于常见问题分析。

鸿蒙跨端适配要点

  • 安全区与滚动:SafeAreaView 与 ScrollView 需由 RN 的鸿蒙适配层桥接到 ArkUI 容器与滚动组件,保证手势、回弹与阻尼一致。
  • 系统能力桥接:拨号、深度链接(物流)、通知或权限引导必须通过 NativeModule/JSI 封装,页面只关心调用与结果。鸿蒙端使用 Ability/Router/权限管理接口,统一错误码与返回值。
  • 图标一致性:emoji 在不同系统字体下表现差异;统一图标栈(SVG/字体)并在鸿蒙端通过 ArkUI 渲染能力映射。
  • 时间与本地化:时间字符串直接展示,建议用日期库统一格式化并处理时区与 locale,确保三端显示一致。
  • 尺寸与旋转:当前使用 Dimensions 的初始宽度;横竖屏/分屏场景建议改用 useWindowDimensions,鸿蒙端需确保窗口事件正确传递至 RN 层。

概述

本文分析的是一个基于React Native构建的订单详情管理应用,集成了订单状态展示、商品信息、物流跟踪、交互操作等核心功能。该应用采用了组件化的状态管理、灵活的数据展示和丰富的交互设计,展现了电商类应用的典型技术架构。在鸿蒙OS的跨端适配场景中,这种涉及复杂数据展示和多层次交互的应用具有重要的技术参考价值。

核心架构设计深度解析

组件化状态管理系统

应用采用了集中的状态管理策略,通过单一的order状态对象维护所有订单相关信息:

const [order] = useState({
  id: 'ORD-20230615-001',
  status: '配送中',
  date: '2023-06-15 14:30',
  total: 345.60,
  paymentMethod: '微信支付',
  shippingAddress: '北京市朝阳区建国路88号SOHO现代城A座',
  receiver: '张三',
  phone: '138****8888',
  items: [
    { id: '1', name: '运动跑步鞋', price: 299.00, quantity: 1, image: '👟' },
    { id: '2', name: '运动水壶', price: 46.60, quantity: 1, image: '💧' },
  ],
  shippingMethod: '顺丰快递',
  trackingNumber: 'SF1234567890',
  notes: '请放置在门口',
});

这种集中式状态管理的优势在于数据流向清晰,便于维护和调试。所有组件都依赖于同一个数据源,确保了数据的一致性。同时,这样的结构也便于与后端API对接,实现数据的持久化和同步。

在鸿蒙ArkUI体系中,状态管理采用了不同的模式,需要通过@State装饰器来定义响应式状态:

@State order: Order = {
  id: 'ORD-20230615-001',
  status: '配送中',
  // ...其他字段
};

interface Order {
  id: string;
  status: string;
  date: string;
  total: number;
  paymentMethod: string;
  shippingAddress: string;
  receiver: string;
  phone: string;
  items: OrderItem[];
  shippingMethod: string;
  trackingNumber: string;
  notes: string;
}

interface OrderItem {
  id: string;
  name: string;
  price: number;
  quantity: number;
  image: string;
}

状态驱动的UI组件

OrderStatus组件采用了状态驱动的设计模式,根据订单状态动态显示不同的颜色和文本:

const OrderStatus = ({ status }: { status: string }) => {
  const getStatusColor = () => {
    switch (status) {
      case '已下单':
        return '#f59e0b';
      case '已支付':
        return '#3b82f6';
      case '配送中':
        return '#f59e0b';
      case '已完成':
        return '#10b981';
      case '已取消':
        return '#ef4444';
      default:
        return '#94a3b8';
    }
  };

  return (
    <View style={[styles.statusContainer, { borderColor: getStatusColor() }]}>
      <Text style={[styles.statusText, { color: getStatusColor() }]}>{status}</Text>
    </View>
  );
};

这种设计模式的优势在于组件的高度可复用性,相同的组件可以用于显示不同的订单状态,而无需修改组件内部逻辑。状态与表现的分离使得维护更加容易,当需要添加新的订单状态时,只需在getStatusColor函数中添加相应的case即可。

鸿蒙平台上的实现需要适配其声明式UI系统:

@Component
struct OrderStatus {
  @Prop status: string;
  
  getStatusColor(): Color {
    switch (this.status) {
      case '已下单':
        return Color.Yellow;
      case '已支付':
        return Color.Blue;
      case '配送中':
        return Color.Yellow;
      case '已完成':
        return Color.Green;
      case '已取消':
        return Color.Red;
      default:
        return Color.Gray;
    }
  }
  
  build() {
    Column() {
      Text(this.status)
    }
    .border({ width: 1, color: this.getStatusColor() })
    .borderRadius(12)
    .padding({ horizontal: 12, vertical: 4 })
  }
}

复杂的布局结构

应用采用了多层次嵌套的布局结构,通过ScrollView包裹多个内容区块:

<ScrollView style={styles.content}>
  {/* 订单状态卡片 */}
  <View style={styles.statusCard}>
    {/* 状态内容 */}
  </View>

  {/* 商品列表 */}
  <View style={styles.sectionCard}>
    {/* 商品内容 */}
  </View>

  {/* 收货信息 */}
  <View style={styles.sectionCard}>
    {/* 收货内容 */}
  </View>

  {/* 订单信息 */}
  <View style={styles.sectionCard}>
    {/* 订单内容 */}
  </View>

  {/* 订单操作 */}
  <View style={styles.actionContainer}>
    {/* 操作按钮 */}
  </View>

  {/* 订单流程指示器 */}
  <View style={styles.progressContainer}>
    {/* 流程步骤 */}
  </View>

  {/* 常见问题 */}
  <View style={styles.questionCard}>
    {/* 问题列表 */}
  </View>
</ScrollView>

这种布局结构的优势在于信息的层次分明,用户可以通过滚动浏览完整的订单详情。每个sectionCard都采用了统一的样式,保持了界面的整体一致性。同时,这种模块化的设计也便于维护和扩展。

鸿蒙平台上的布局实现采用了类似的嵌套结构,但需要使用Column和Row等布局组件:

Scroll() {
  Column() {
    // 订单状态卡片
    Column() {
      // 状态内容
    }
    .backgroundColor(Color.White)
    .borderRadius(12)
    .margin({ bottom: 16 })

    // 商品列表
    Column() {
      // 商品内容
    }
    .backgroundColor(Color.White)
    .borderRadius(12)
    .margin({ bottom: 16 })
    
    // 其他区块...
  }
  .padding(16)
}

交互设计与用户体验

丰富的操作按钮

应用提供了多种交互操作,包括查看物流、联系客服和取消订单:

const handleContactSupport = () => {
  Alert.alert('联系客服', '拨打客服电话: 400-123-4567', [
    { text: '取消', style: 'cancel' },
    { text: '呼叫', onPress: () => console.log('Call support') }
  ]);
};

const handleTrackOrder = () => {
  Alert.alert('物流跟踪', `物流单号: ${order.trackingNumber}\n正在跳转到物流详情页面...`, [
    { text: '确定', onPress: () => console.log('Track order') }
  ]);
};

const handleCancelOrder = () => {
  Alert.alert(
    '取消订单',
    '确定要取消此订单吗?',
    [
      { text: '取消', style: 'cancel' },
      { 
        text: '确定', 
        style: 'destructive',
        onPress: () => Alert.alert('提示', '订单已取消')
      }
    ]
  );
};

这些交互设计体现了良好的用户体验考虑。联系客服操作提供了明确的电话号码和确认机制,物流跟踪显示了详细的物流信息,取消订单操作则包含了二次确认防止误操作。

鸿蒙平台的对话框实现需要使用prompt模块:

import prompt from '@ohos.prompt';

async handleContactSupport() {
  const result = await prompt.showDialog({
    title: '联系客服',
    message: '拨打客服电话: 400-123-4567',
    buttons: [
      { text: '取消', color: '#666666' },
      { text: '呼叫', color: '#007AFF' }
    ]
  });
  
  if (result.index === 1) {
    // 处理呼叫逻辑
  }
}

订单流程可视化

应用通过进度指示器直观展示订单的处理流程:

<View style={styles.progressContainer}>
  <View style={styles.progressStep}>
    <View style={[styles.stepCircle, { backgroundColor: '#10b981' }]}>
      <Text style={styles.stepIcon}>{ICONS.order}</Text>
    </View>
    <Text style={styles.stepText}>已下单</Text>
  </View>
  <View style={styles.progressLine}></View>
  <View style={styles.progressStep}>
    <View style={[styles.stepCircle, { backgroundColor: '#3b82f6' }]}>
      <Text style={styles.stepIcon}>{ICONS.payment}</Text>
    </View>
    <Text style={styles.stepText}>已支付</Text>
  </View>
  {/* 更多步骤 */}
</View>

这种可视化设计让用户能够清晰了解订单的当前状态和后续流程,提升了用户体验。每个步骤都包含了图标和文字说明,连接线则表明了流程的顺序关系。

鸿蒙平台上的进度指示器实现需要使用Stack和Flex布局:

Row() {
  ForEach(this.steps, (step, index) => {
    Column() {
      // 步骤圆圈
      Stack() {
        Text(step.icon)
      }
      .width(40)
      .height(40)
      .borderRadius(20)
      .backgroundColor(step.color)
      
      Text(step.text)
    }
    
    // 连接线(非最后一个步骤)
    if (index < this.steps.length - 1) {
      Column()
        .height(2)
        .backgroundColor('#CBD5E1')
        .margin({ horizontal: 8 })
    }
  })
}

跨端适配技术方案

组件映射策略

React Native组件 鸿蒙ArkUI组件 适配说明
ScrollView Scroll 滚动行为基本一致
TouchableOpacity Button 交互反馈需要调整
Alert.alert prompt.showDialog 对话框API完全不同
View Column/Row/Stack 布局方式需要转换

样式系统转换

尺寸和颜色的转换相对直接:

// React Native样式
borderRadius: 12,
padding: 16,
backgroundColor: '#ffffff',

// 鸿蒙样式
.borderRadius(12)
.padding(16)
.backgroundColor(Color.White)

阴影效果需要适配:

// React Native阴影
elevation: 1,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,

// 鸿蒙阴影
.shadow({
  radius: 2,
  color: '#000000',
  offsetX: 0,
  offsetY: 1,
  opacity: 0.1
})

交互反馈适配

触摸反馈的实现方式存在差异:

// React Native
<TouchableOpacity onPress={handlePress}>
  <Text>按钮</Text>
</TouchableOpacity>

// 鸿蒙
Button('按钮', { type: ButtonType.Normal })
  .onClick(() => this.handlePress())

性能优化与最佳实践

列表渲染优化

对于可能包含大量商品的项目列表,应该使用FlatList替代ScrollView+map:

<FlatList
  data={order.items}
  renderItem={({ item }) => <OrderItem {...item} />}
  keyExtractor={(item) => item.id}
/>

鸿蒙平台的List组件支持虚拟化渲染:

List() {
  ForEach(this.order.items, (item: OrderItem) => {
    ListItem() {
      OrderItemComponent({ item: item })
    }
  })
}

图片加载优化

对于商品图片,应该实现懒加载和缓存机制:

// React Native中使用FastImage或其他优化库
<FastImage
  source={{ uri: item.imageUrl }}
  resizeMode={FastImage.resizeMode.contain}
/>

鸿蒙平台提供了Image组件的优化选项:

Image(item.imageUrl)
  .objectFit(ImageFit.Contain)
  .interpolation(ImageInterpolation.High)

总结与实施建议

这个React Native订单详情应用展示了电商类应用的典型技术架构,其组件化的状态管理、丰富的交互设计和良好的用户体验为鸿蒙跨端适配提供了优秀的基础。


完整代码:


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

// 图标库
const ICONS = {
  order: '📦',
  product: '🛍️',
  payment: '💳',
  shipping: '🚚',
  user: '👤',
  phone: '📞',
  location: '📍',
  support: '❓',
};

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

// 订单状态组件
const OrderStatus = ({ status }: { status: string }) => {
  const getStatusColor = () => {
    switch (status) {
      case '已下单':
        return '#f59e0b';
      case '已支付':
        return '#3b82f6';
      case '配送中':
        return '#f59e0b';
      case '已完成':
        return '#10b981';
      case '已取消':
        return '#ef4444';
      default:
        return '#94a3b8';
    }
  };

  return (
    <View style={[styles.statusContainer, { borderColor: getStatusColor() }]}>
      <Text style={[styles.statusText, { color: getStatusColor() }]}>{status}</Text>
    </View>
  );
};

// 订单商品组件
const OrderItem = ({ 
  name, 
  price, 
  quantity, 
  image 
}: { 
  name: string; 
  price: number; 
  quantity: number; 
  image: string 
}) => {
  return (
    <View style={styles.orderItem}>
      <View style={styles.itemImage}>
        <Text style={styles.itemImageText}>{image}</Text>
      </View>
      <View style={styles.itemInfo}>
        <Text style={styles.itemName}>{name}</Text>
        <Text style={styles.itemPrice}>¥{price.toFixed(2)} × {quantity}</Text>
      </View>
      <Text style={styles.itemTotal}>¥{(price * quantity).toFixed(2)}</Text>
    </View>
  );
};

// 订单详情组件
const OrderDetail = ({ label, value, isImportant = false }: { label: string; value: string; isImportant?: boolean }) => {
  return (
    <View style={styles.detailRow}>
      <Text style={styles.detailLabel}>{label}</Text>
      <Text style={[styles.detailValue, isImportant && styles.importantValue]}>{value}</Text>
    </View>
  );
};

// 主页面组件
const SportOrderDetailApp: React.FC = () => {
  const [order] = useState({
    id: 'ORD-20230615-001',
    status: '配送中',
    date: '2023-06-15 14:30',
    total: 345.60,
    paymentMethod: '微信支付',
    shippingAddress: '北京市朝阳区建国路88号SOHO现代城A座',
    receiver: '张三',
    phone: '138****8888',
    items: [
      { id: '1', name: '运动跑步鞋', price: 299.00, quantity: 1, image: '👟' },
      { id: '2', name: '运动水壶', price: 46.60, quantity: 1, image: '💧' },
    ],
    shippingMethod: '顺丰快递',
    trackingNumber: 'SF1234567890',
    notes: '请放置在门口',
  });

  const handleContactSupport = () => {
    Alert.alert('联系客服', '拨打客服电话: 400-123-4567', [
      { text: '取消', style: 'cancel' },
      { text: '呼叫', onPress: () => console.log('Call support') }
    ]);
  };

  const handleTrackOrder = () => {
    Alert.alert('物流跟踪', `物流单号: ${order.trackingNumber}\n正在跳转到物流详情页面...`, [
      { text: '确定', onPress: () => console.log('Track order') }
    ]);
  };

  const handleCancelOrder = () => {
    Alert.alert(
      '取消订单',
      '确定要取消此订单吗?',
      [
        { text: '取消', style: 'cancel' },
        { 
          text: '确定', 
          style: 'destructive',
          onPress: () => Alert.alert('提示', '订单已取消')
        }
      ]
    );
  };

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <TouchableOpacity onPress={() => Alert.alert('返回')}>
          <Text style={styles.backButton}>← 返回</Text>
        </TouchableOpacity>
        <Text style={styles.title}>订单详情</Text>
        <View style={{ width: 24 }}></View> {/* 占位符保持居中 */}
      </View>

      <ScrollView style={styles.content}>
        {/* 订单状态卡片 */}
        <View style={styles.statusCard}>
          <View style={styles.statusHeader}>
            <Text style={styles.orderId}>订单号: {order.id}</Text>
            <OrderStatus status={order.status} />
          </View>
          <Text style={styles.orderDate}>下单时间: {order.date}</Text>
        </View>

        {/* 商品列表 */}
        <View style={styles.sectionCard}>
          <Text style={styles.sectionTitle}>商品信息</Text>
          {order.items.map(item => (
            <OrderItem
              key={item.id}
              name={item.name}
              price={item.price}
              quantity={item.quantity}
              image={item.image}
            />
          ))}
          <View style={styles.totalRow}>
            <Text style={styles.totalLabel}>总计:</Text>
            <Text style={styles.totalValue}>¥{order.total.toFixed(2)}</Text>
          </View>
        </View>

        {/* 收货信息 */}
        <View style={styles.sectionCard}>
          <Text style={styles.sectionTitle}>收货信息</Text>
          <OrderDetail label="收货人" value={order.receiver} isImportant />
          <OrderDetail label="联系电话" value={order.phone} isImportant />
          <OrderDetail label="收货地址" value={order.shippingAddress} isImportant />
        </View>

        {/* 订单信息 */}
        <View style={styles.sectionCard}>
          <Text style={styles.sectionTitle}>订单信息</Text>
          <OrderDetail label="支付方式" value={order.paymentMethod} />
          <OrderDetail label="配送方式" value={order.shippingMethod} />
          <OrderDetail label="物流单号" value={order.trackingNumber} />
          <OrderDetail label="订单备注" value={order.notes || '无'} />
        </View>

        {/* 订单操作 */}
        <View style={styles.actionContainer}>
          <TouchableOpacity style={styles.actionButton} onPress={handleTrackOrder}>
            <Text style={styles.actionButtonText}>查看物流</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.actionButton} onPress={handleContactSupport}>
            <Text style={styles.actionButtonText}>联系客服</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.cancelButton} onPress={handleCancelOrder}>
            <Text style={styles.cancelButtonText}>取消订单</Text>
          </TouchableOpacity>
        </View>

        {/* 订单流程指示器 */}
        <Text style={styles.sectionTitle}>订单流程</Text>
        <View style={styles.progressContainer}>
          <View style={styles.progressStep}>
            <View style={[styles.stepCircle, { backgroundColor: '#10b981' }]}>
              <Text style={styles.stepIcon}>{ICONS.order}</Text>
            </View>
            <Text style={styles.stepText}>已下单</Text>
          </View>
          <View style={styles.progressLine}></View>
          <View style={styles.progressStep}>
            <View style={[styles.stepCircle, { backgroundColor: '#3b82f6' }]}>
              <Text style={styles.stepIcon}>{ICONS.payment}</Text>
            </View>
            <Text style={styles.stepText}>已支付</Text>
          </View>
          <View style={styles.progressLine}></View>
          <View style={styles.progressStep}>
            <View style={[styles.stepCircle, { backgroundColor: '#f59e0b' }]}>
              <Text style={styles.stepIcon}>{ICONS.shipping}</Text>
            </View>
            <Text style={styles.stepText}>配送中</Text>
          </View>
          <View style={styles.progressLine}></View>
          <View style={styles.progressStep}>
            <View style={[styles.stepCircle, { backgroundColor: '#cbd5e1' }]}>
              <Text style={styles.stepIcon}>{ICONS.product}</Text>
            </View>
            <Text style={styles.stepText}>已完成</Text>
          </View>
        </View>

        {/* 常见问题 */}
        <Text style={styles.sectionTitle}>常见问题</Text>
        <View style={styles.questionCard}>
          <TouchableOpacity style={styles.questionItem} onPress={() => Alert.alert('如何修改收货地址?', '订单已发货后无法修改收货地址')}>
            <Text style={styles.questionText}>• 如何修改收货地址?</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.questionItem} onPress={() => Alert.alert('多久能收到货?', '通常在发货后1-3个工作日内送达')}>
            <Text style={styles.questionText}>• 多久能收到货?</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.questionItem} onPress={() => Alert.alert('如何申请退换货?', '请在订单完成后联系客服申请')}>
            <Text style={styles.questionText}>• 如何申请退换货?</Text>
          </TouchableOpacity>
        </View>
      </ScrollView>

      {/* 底部导航 */}
      <View style={styles.bottomNav}>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.product}</Text>
          <Text style={styles.navText}>商城</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.shipping}</Text>
          <Text style={styles.navText}>订单</Text>
        </TouchableOpacity>
        <TouchableOpacity style={[styles.navItem, styles.activeNavItem]}>
          <Text style={styles.navIcon}>{ICONS.order}</Text>
          <Text style={styles.navText}>详情</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.user}</Text>
          <Text style={styles.navText}>我的</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: 20,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  backButton: {
    fontSize: 16,
    color: '#3b82f6',
    fontWeight: '500',
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  content: {
    flex: 1,
    padding: 16,
  },
  statusCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  statusHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8,
  },
  orderId: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  statusContainer: {
    borderWidth: 1,
    borderRadius: 12,
    paddingHorizontal: 12,
    paddingVertical: 4,
  },
  statusText: {
    fontSize: 14,
    fontWeight: '500',
  },
  orderDate: {
    fontSize: 14,
    color: '#64748b',
  },
  sectionCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 12,
  },
  orderItem: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  orderItemLast: {
    borderBottomWidth: 0,
  },
  itemImage: {
    width: 50,
    height: 50,
    borderRadius: 8,
    backgroundColor: '#f1f5f9',
    alignItems: 'center',
    justifyContent: 'center',
    marginRight: 12,
  },
  itemImageText: {
    fontSize: 24,
  },
  itemInfo: {
    flex: 1,
  },
  itemName: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
  },
  itemPrice: {
    fontSize: 14,
    color: '#64748b',
    marginTop: 4,
  },
  itemTotal: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  totalRow: {
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
    paddingTop: 12,
    marginTop: 8,
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
  },
  totalLabel: {
    fontSize: 16,
    color: '#64748b',
    marginRight: 8,
  },
  totalValue: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  detailRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 8,
  },
  detailLabel: {
    fontSize: 14,
    color: '#64748b',
  },
  detailValue: {
    fontSize: 14,
    color: '#1e293b',
    textAlign: 'right',
  },
  importantValue: {
    fontWeight: '500',
  },
  actionContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginBottom: 16,
  },
  actionButton: {
    flex: 1,
    backgroundColor: '#f1f5f9',
    padding: 12,
    borderRadius: 8,
    alignItems: 'center',
    marginRight: 8,
  },
  actionButtonText: {
    color: '#3b82f6',
    fontWeight: '500',
  },
  cancelButton: {
    flex: 1,
    backgroundColor: '#fee2e2',
    padding: 12,
    borderRadius: 8,
    alignItems: 'center',
    marginLeft: 8,
  },
  cancelButtonText: {
    color: '#dc2626',
    fontWeight: '500',
  },
  progressContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
  },
  progressStep: {
    alignItems: 'center',
    flex: 1,
  },
  stepCircle: {
    width: 40,
    height: 40,
    borderRadius: 20,
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 8,
  },
  stepIcon: {
    fontSize: 18,
    color: '#ffffff',
  },
  stepText: {
    fontSize: 12,
    color: '#64748b',
    textAlign: 'center',
  },
  progressLine: {
    flex: 1,
    height: 2,
    backgroundColor: '#cbd5e1',
    marginHorizontal: -20,
  },
  questionCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
  },
  questionItem: {
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  questionItemLast: {
    borderBottomWidth: 0,
  },
  questionText: {
    fontSize: 14,
    color: '#1e293b',
  },
  bottomNav: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    paddingVertical: 12,
  },
  navItem: {
    alignItems: 'center',
    flex: 1,
  },
  activeNavItem: {
    paddingBottom: 2,
    borderBottomWidth: 2,
    borderBottomColor: '#3b82f6',
  },
  navIcon: {
    fontSize: 20,
    color: '#94a3b8',
    marginBottom: 4,
  },
  activeNavIcon: {
    color: '#3b82f6',
  },
  navText: {
    fontSize: 12,
    color: '#94a3b8',
  },
  activeNavText: {
    color: '#3b82f6',
    fontWeight: '500',
  },
});

export default SportOrderDetailApp;

请添加图片描述

打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述

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

Logo

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

更多推荐