在电商应用中,支付系统是用户完成购买流程的最后一环,其设计质量直接影响用户的购买体验和转化率。本文将深入分析一个基于 React Native 实现的支付应用系统,探讨其架构设计、技术实现以及鸿蒙跨端适配策略。

核心数据

该系统构建了两个核心数据模型,为支付流程提供了完整的数据支持:

// 支付方式类型
type PaymentMethod = {
  id: string;
  name: string;
  icon: string;
  description: string;
  fee?: number;
};

// 订单信息类型
type OrderInfo = {
  orderId: string;
  amount: number;
  items: number;
  status: 'pending' | 'paid' | 'cancelled';
};

这种数据模型设计的优势:

  • 完整性:涵盖了支付方式和订单信息的核心属性
  • 类型安全:使用 TypeScript 类型确保数据结构一致性
  • 扩展性:支持添加更多属性,如支付方式的图标、费用等
  • 灵活性:订单状态使用联合类型,支持多种状态管理

状态管理

系统采用了 React Hooks 中的 useState 进行轻量级状态管理:

const [orderInfo] = useState<OrderInfo>({
  orderId: 'ORD202310120001',
  amount: 18497,
  items: 3,
  status: 'pending'
});

const [paymentMethods] = useState<PaymentMethod[]>([
  // 支付方式数据...
]);

const [selectedMethod, setSelectedMethod] = useState<string>('alipay');
const [agreed, setAgreed] = useState<boolean>(true);

这种状态管理方式具有以下优势:

  • 模块化:将不同类型的数据分离管理,提高代码可读性
  • 响应式:状态变更自动触发组件重渲染,确保 UI 与数据同步
  • 跨端兼容:React Hooks 在鸿蒙系统的 React Native 实现中通常都有良好支持
  • 简洁性:代码结构清晰,易于理解和维护

系统实现了完整的支付流程,包括:

支付方式选择

支付方式选择功能支持用户从多种支付方式中选择一种进行支付,每种支付方式都有详细的描述和费用说明。通过状态管理,实时更新用户选择的支付方式,并提供清晰的视觉反馈。

订单摘要显示

订单摘要显示功能展示了订单的核心信息,包括商品数量、商品金额、运费和应付总额,让用户在支付前对订单金额有清晰的了解。

支付处理

支付处理功能是系统的核心,实现了以下逻辑:

  • 验证用户是否同意支付协议
  • 计算最终支付金额(包括可能的支付方式费用)
  • 显示支付确认对话框,让用户确认支付信息
  • 模拟支付过程,显示支付成功提示
const handlePayment = () => {
  if (!agreed) {
    Alert.alert('提示', '请同意支付协议');
    return;
  }

  const method = paymentMethods.find(m => m.id === selectedMethod);
  Alert.alert(
    '支付确认',
    `您选择使用${method?.name}支付 ¥${orderInfo.amount + (method?.fee || 0)}\n\n订单号: ${orderInfo.orderId}`,
    [
      {
        text: '取消',
        style: 'cancel'
      },
      {
        text: '确认支付',
        onPress: () => {
          // 模拟支付过程
          Alert.alert(
            '支付成功',
            '您的订单已支付成功!\n\n订单号: ORD202310120001',
            [
              {
                text: '确定',
                onPress: () => console.log('支付完成')
              }
            ]
          );
        }
      }
    ]
  );
};

基础架构

该实现采用了 React Native 核心组件库,确保了在鸿蒙系统上的基本兼容性:

  • SafeAreaView:适配刘海屏等异形屏
  • ScrollView:处理内容滚动,确保长页面可浏览
  • TouchableOpacity:提供触摸反馈,增强用户体验
  • TextView:构建基本 UI 结构
  • Image:显示图标和其他视觉元素
  • Alert:系统级弹窗提示,提供操作反馈

Base64 图标

系统使用 Base64 编码的图标库,这种处理方式在跨端开发中尤为重要:

  • 避免了不同平台对资源文件格式的兼容性问题
  • 减少了网络请求,提高了加载速度
  • 简化了构建流程,无需处理多平台资源文件
  • 确保图标在不同设备上的显示一致性

屏幕尺寸

系统通过 Dimensions API 获取屏幕尺寸,确保了在不同屏幕尺寸的设备上都能获得一致的布局体验,无论是 React Native 环境还是鸿蒙系统:

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

系统实现了流畅的交互体验:

  • 支付方式选择:点击支付方式后立即更新选中状态,提供清晰的视觉反馈
  • 协议同意:支持切换协议同意状态,未同意时阻止支付
  • 支付确认:点击支付按钮后显示确认对话框,让用户再次确认支付信息
  • 支付反馈:模拟支付过程后显示支付成功提示,完成支付流程
  • 滚动体验:长页面支持流畅滚动,确保所有信息都能被浏览

系统采用了模块化的样式定义,确保了样式的一致性和可维护性:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  // 其他样式...
});

这种方式为后续的主题定制和深色模式适配预留了扩展空间。


在鸿蒙系统上使用 React Native 时,应注意以下 API 兼容性问题:

  1. Alert API:鸿蒙系统的 Alert 实现可能与 React Native 有所差异,建议测试确认弹窗行为
  2. ScrollView API:鸿蒙系统的 ScrollView 实现可能与 React Native 有所差异,建议测试确认滚动行为
  3. TouchableOpacity API:鸿蒙系统的 TouchableOpacity 实现可能与 React Native 有所差异,建议测试确认触摸反馈

本支付系统实现了一个功能完整、用户友好的支付界面,通过合理的架构设计和代码组织,为用户提供了良好的支付体验。在跨端开发场景下,该实现充分考虑了 React Native 和鸿蒙系统的兼容性需求,为后续的功能扩展和性能优化预留了空间。

通过支付方式选择、订单摘要显示、支付处理等核心功能,结合 Base64 图标处理、屏幕尺寸适配等技术手段,该系统不仅功能完善,而且具有良好的可维护性和可扩展性。这些实践经验对于构建其他跨端应用组件也具有参考价值。


支付订单页是电商交易闭环的最后一环,其核心价值在于清晰展示订单信息、提供安全便捷的支付方式选择、完成支付流程的交互闭环。本文将深度拆解这份基于 React Native 构建的支付订单应用代码,从数据模型设计、状态管理体系、交互逻辑架构、视觉布局规范四个维度剖析其技术内核,并提供完整的鸿蒙(HarmonyOS)ArkTS 跨端适配方案,为跨端电商支付场景开发提供可落地的技术参考。

1. 支付场景

支付订单页的核心是整合订单核心信息 + 支付方式配置,代码通过 TypeScript 构建了精准匹配支付场景的两类核心数据模型:

// 支付方式类型:覆盖支付方式全维度信息
type PaymentMethod = {
  id: string;           // 支付方式唯一标识
  name: string;         // 支付方式名称
  icon: string;         // 支付方式图标(emoji/Base64)
  description: string;  // 支付方式描述
  fee?: number;         // 支付手续费(可选)
};

// 订单信息类型:覆盖支付所需的核心订单属性
type OrderInfo = {
  orderId: string;      // 订单唯一标识
  amount: number;       // 订单金额
  items: number;        // 商品数量
  status: 'pending' | 'paid' | 'cancelled'; // 订单状态
};

设计亮点分析:

  • 场景贴合度高:PaymentMethod 模型包含 fee 可选字段,精准覆盖不同支付方式的手续费规则,符合真实支付场景需求;
  • 状态约束严格:OrderInfo 的 status 字段使用联合类型,限定仅能为 pending/paid/cancelled 三种状态,避免非法状态值;
  • 扩展性良好icon 字段支持 emoji/Base64 等多种形式,fee 可选字段兼容有无手续费的支付方式;
  • 类型安全保障:通过 TypeScript 类型定义,确保初始化数据和状态更新的类型安全,避免运行时错误;
  • 核心信息完整:OrderInfo 包含订单支付所需的核心字段(订单号、金额、商品数量、状态),无冗余也无缺失。

2. 支付核心状态

支付订单页的核心价值在于支付方式选择 + 支付流程校验 + 支付结果反馈,代码通过 React 的 useState 构建了完整的状态管理体系,覆盖支付全流程操作:

(1)核心状态初始化
// 订单核心信息:静态数据,支付过程中不变化
const [orderInfo] = useState<OrderInfo>({
  orderId: 'ORD202310120001',
  amount: 18497,
  items: 3,
  status: 'pending'
});

// 支付方式列表:包含不同支付方式的配置信息
const [paymentMethods] = useState<PaymentMethod[]>([
  { id: 'alipay', name: '支付宝', icon: '💳', description: '使用支付宝支付', fee: 0 },
  { id: 'wechat', name: '微信支付', icon: '💬', description: '使用微信支付', fee: 0 },
  { id: 'credit', name: '信用卡', icon: '💳', description: '使用信用卡支付', fee: 5 },
  { id: 'debit', name: '借记卡', icon: '💳', description: '使用借记卡支付', fee: 0 },
  { id: 'bank', name: '银行转账', icon: '🏦', description: '使用银行转账', fee: 2 },
]);

// 选中的支付方式:默认支付宝
const [selectedMethod, setSelectedMethod] = useState<string>('alipay');

// 协议同意状态:默认同意,保障支付流程合规性
const [agreed, setAgreed] = useState<boolean>(true);

初始化策略:

  • 数据分层管理:静态数据(订单信息、支付方式列表)与动态选择状态(选中支付方式、协议同意状态)分离,符合状态管理最佳实践;
  • 默认值合理:默认选中支付宝(主流支付方式)、默认同意协议,贴合用户使用习惯;
  • 不可变初始化:静态数据使用 const [x] = useState() 声明,避免不必要的重渲染;
  • 合规性前置:协议同意状态默认 true,但保留可切换能力,符合支付场景的合规要求。
(2)支付核心业务逻辑

const handlePayment = () => {
  // 1. 协议校验:支付前必须同意协议
  if (!agreed) {
    Alert.alert('提示', '请同意支付协议');
    return;
  }

  // 2. 获取选中的支付方式信息
  const method = paymentMethods.find(m => m.id === selectedMethod);
  
  // 3. 支付确认弹窗:展示最终支付金额(含手续费)
  Alert.alert(
    '支付确认',
    `您选择使用${method?.name}支付 ¥${orderInfo.amount + (method?.fee || 0)}\n\n订单号: ${orderInfo.orderId}`,
    [
      {
        text: '取消',
        style: 'cancel'
      },
      {
        text: '确认支付',
        onPress: () => {
          // 4. 模拟支付成功反馈
          Alert.alert(
            '支付成功',
            '您的订单已支付成功!\n\n订单号: ORD202310120001',
            [
              {
                text: '确定',
                onPress: () => console.log('支付完成')
              }
            ]
          );
        }
      }
    ]
  );
};

设计亮点:

  • 流程校验前置:支付前先校验协议同意状态,避免无效的支付操作;
  • 金额计算精准:最终支付金额 = 订单金额 + 支付手续费,自动适配不同支付方式的手续费规则;
  • 空值保护:使用可选链操作符 ?. 和默认值 || 0,避免支付方式不存在时的空值错误;
  • 交互闭环完整:包含“校验-确认-支付-反馈”完整流程,符合用户支付操作习惯;
  • 用户反馈清晰:通过多层弹窗提供明确的操作反馈,包含订单号、支付金额等关键信息;
  • 扩展性预留console.log 位置可直接替换为真实的支付 API 调用,便于对接支付网关。

支付订单页采用信息分层展示 + 支付方式选择 + 安全提示 + 支付操作的经典支付布局,结合 React Native 的组件特性,打造安全、清晰的支付体验:

(1)整体布局
SafeAreaView
├── Header(头部:标题 + 订单号)
├── ScrollView(滚动内容区)
│   ├── OrderSummary(订单摘要/金额明细)
│   ├── Section(支付方式选择)
│   ├── SecurityCard(安全提示)
│   ├── AgreementSection(协议确认)
│   └── CountdownCard(支付倒计时)
├── BottomBar(底部支付栏:实付金额 + 支付按钮)
└── BottomNav(底部导航:首页/分类/购物车/我的)

布局设计优势:

  • 信息分层清晰:按“订单信息-支付方式-安全提示-协议确认-倒计时”的逻辑顺序排列,符合用户支付决策路径;
  • 滚动适配:内容区使用 ScrollView 包裹,适配多支付方式、长文本提示的场景;
  • 固定操作区:底部支付栏固定在页面底部,始终处于用户视野,降低支付操作成本;
  • 安全区域适配:使用 SafeAreaView 适配刘海屏/全面屏,避免内容被遮挡;
  • 视觉分层:通过卡片式设计(borderRadius/shadow)区分不同功能区域,提升视觉层次感;
  • 支付紧迫感:增加支付倒计时模块,营造支付时效感,符合电商支付场景设计规范。

① 支付方式选择
{paymentMethods.map(method => (
  <TouchableOpacity
    key={method.id}
    style={[
      styles.paymentOption,
      selectedMethod === method.id && styles.selectedPaymentOption
    ]}
    onPress={() => setSelectedMethod(method.id)}
  >
    <View style={styles.paymentOptionContent}>
      <Text style={styles.paymentIcon}>{method.icon}</Text>
      <View style={styles.paymentInfo}>
        <Text style={styles.paymentName}>{method.name}</Text>
        <Text style={styles.paymentDescription}>{method.description}</Text>
      </View>
      {method.fee && method.fee > 0 && (
        <Text style={styles.feeText}>+¥{method.fee}</Text>
      )}
    </View>
    {selectedMethod === method.id && (
      <Text style={styles.checkIcon}></Text>
    )}
  </TouchableOpacity>
))}

交互设计亮点:

  • 状态联动:选中状态通过样式类(背景色+边框)和勾选图标双重反馈,视觉清晰;
  • 手续费提示:条件渲染手续费信息(method.fee && method.fee > 0),让用户明确知晓额外成本;
  • 通用化渲染:通过数组 map 渲染所有支付方式,避免重复代码;
  • 视觉区分:选中项使用蓝色边框+浅蓝色背景,未选中项使用浅灰色背景,对比明显;
  • 信息完整:展示图标、名称、描述、手续费,满足用户选择支付方式的决策需求。
② 协议确认复选框
<TouchableOpacity 
  style={styles.checkboxContainer}
  onPress={() => setAgreed(!agreed)}
>
  <View style={[styles.checkbox, agreed && styles.checkboxChecked]}>
    {agreed && <Text style={styles.checkboxCheck}></Text>}
  </View>
  <Text style={styles.agreementText}>
    我已阅读并同意 <Text style={styles.linkText}>《支付协议》</Text><Text style={styles.linkText}>《隐私政策》</Text>
  </Text>
</TouchableOpacity>

交互设计亮点:

  • 自定义复选框:通过 View + Text 实现样式统一的复选框,避免原生组件样式差异;
  • 状态反馈清晰:选中时背景色+勾选标记,未选中时仅边框,视觉反馈明确;
  • 合规性设计:协议文本包含可点击链接样式(linkText),符合支付合规要求;
  • 操作便捷:整个行均可点击切换状态,点击区域大,操作体验佳;
  • 文本排版:协议文本换行自适应,避免内容溢出。
③ 订单金额摘要
<View style={styles.orderSummary}>
  <Text style={styles.summaryTitle}>订单摘要</Text>
  <View style={styles.summaryRow}>
    <Text style={styles.summaryLabel}>商品数量</Text>
    <Text style={styles.summaryValue}>{orderInfo.items}</Text>
  </View>
  <View style={styles.summaryRow}>
    <Text style={styles.summaryLabel}>商品金额</Text>
    <Text style={styles.summaryValue}>¥{orderInfo.amount}</Text>
  </View>
  <View style={styles.summaryRow}>
    <Text style={styles.summaryLabel}>运费</Text>
    <Text style={styles.summaryValue}>¥0</Text>
  </View>
  <View style={styles.totalRow}>
    <Text style={styles.totalLabel}>应付总额</Text>
    <Text style={styles.totalValue}>¥{orderInfo.amount}</Text>
  </View>
</View>

设计亮点:

  • 信息层级清晰:商品数量、金额、运费分行展示,总计行通过边框分隔并加粗突出;
  • 视觉优先级:总计金额使用红色+大号字体+加粗,符合用户对金额的视觉关注习惯;
  • 扩展性预留:运费字段默认 0,便于后续接入运费计算逻辑;
  • 数据实时性:直接绑定 orderInfo 状态,确保金额信息准确。
④ 底部支付栏
<View style={styles.bottomBar}>
  <View style={styles.finalAmount}>
    <Text style={styles.finalAmountLabel}>实付金额:</Text>
    <Text style={styles.finalAmountValue}>
      ¥{orderInfo.amount + (paymentMethods.find(m => m.id === selectedMethod)?.fee || 0)}
    </Text>
  </View>
  <TouchableOpacity 
    style={styles.payButton} 
    onPress={handlePayment}
  >
    <Text style={styles.payButtonText}>立即支付</Text>
  </TouchableOpacity>
</View>

设计亮点:

  • 金额实时计算:实付金额自动计算订单金额+选中支付方式的手续费,确保金额准确;
  • 视觉突出:支付按钮使用蓝色背景+白色文字,视觉冲击力强,引导用户点击;
  • 位置固定:底部固定定位,始终可见,符合支付操作的交互习惯;
  • 信息完整:明确标注“实付金额”,避免用户混淆订单金额和最终支付金额。
(3)样式

代码通过 StyleSheet.create 构建了完整的支付订单页样式体系,遵循支付场景视觉规范 + 安全合规性原则:

  • 色彩体系:主色调采用蓝色(#3b82f6),金额色采用红色(#ef4444),倒计时采用暖黄色(#f59e0b),符合支付场景视觉设计规范;
  • 卡片设计:所有功能区域均采用卡片式设计(borderRadius: 12),通过阴影(shadow/elevation)提升视觉层次感;
  • 间距规范:采用 16px/12px/8px/4px 的间距体系,保证页面布局的呼吸感;
  • 文字层级:通过字体大小和字重区分信息重要程度,金额和标题加粗大号,说明文字小号浅色;
  • 选中状态样式:支付方式选中项使用蓝色边框+浅蓝色背景,视觉反馈清晰;
  • 安全提示样式:安全提示卡片使用白色背景,文字浅色,营造安全可靠的视觉感受;
  • 倒计时样式:暖黄色背景+大号数字,突出支付时效,营造紧迫感;
  • 协议文本样式:协议链接使用蓝色文字,符合用户对可点击文本的认知习惯。

将 React Native 支付订单应用迁移至鸿蒙平台,核心是基于 ArkTS + ArkUI 实现数据模型、状态管理、列表渲染、交互逻辑的对等还原,同时适配鸿蒙的组件特性和交互范式,以下是完整的适配方案:

1. 数据模型

RN 的 TypeScript 类型体系可无缝迁移至鸿蒙 ArkTS,仅需调整类型定义语法,核心字段和业务逻辑完全复用:

(1)数据类型
// 鸿蒙 ArkTS 类型定义
interface PaymentMethod {
  id: string;
  name: string;
  icon: string;
  description: string;
  fee?: number;
}

interface OrderInfo {
  orderId: string;
  amount: number;
  items: number;
  status: 'pending' | 'paid' | 'cancelled';
}
(2)状态管理
@Entry
@Component
struct PaymentApp {
  // 订单核心信息:静态数据
  @State orderInfo: OrderInfo = {
    orderId: 'ORD202310120001',
    amount: 18497,
    items: 3,
    status: 'pending'
  };
  
  // 支付方式列表
  @State paymentMethods: PaymentMethod[] = [
    { id: 'alipay', name: '支付宝', icon: '💳', description: '使用支付宝支付', fee: 0 },
    { id: 'wechat', name: '微信支付', icon: '💬', description: '使用微信支付', fee: 0 },
    { id: 'credit', name: '信用卡', icon: '💳', description: '使用信用卡支付', fee: 5 },
    { id: 'debit', name: '借记卡', icon: '💳', description: '使用借记卡支付', fee: 0 },
    { id: 'bank', name: '银行转账', icon: '🏦', description: '使用银行转账', fee: 2 },
  ];
  
  // 动态选择状态
  @State selectedMethod: string = 'alipay';
  @State agreed: boolean = true;
  
  // 支付核心逻辑:完全复用 RN 端逻辑
  handlePayment() {
    // 1. 协议校验
    if (!this.agreed) {
      AlertDialog.show({
        title: '提示',
        message: '请同意支付协议',
        confirm: {
          value: '确定'
        }
      });
      return;
    }

    // 2. 获取选中的支付方式
    const method = this.paymentMethods.find(m => m.id === this.selectedMethod);
    
    // 3. 支付确认弹窗
    AlertDialog.show({
      title: '支付确认',
      message: `您选择使用${method?.name}支付 ¥${this.orderInfo.amount + (method?.fee || 0)}\n\n订单号: ${this.orderInfo.orderId}`,
      cancel: {
        value: '取消'
      },
      confirm: {
        value: '确认支付',
        action: () => {
          // 4. 支付成功反馈
          AlertDialog.show({
            title: '支付成功',
            message: '您的订单已支付成功!\n\n订单号: ORD202310120001',
            confirm: {
              value: '确定',
              action: () => console.log('支付完成')
            }
          });
        }
      }
    });
  }
  
  // 页面主构建函数
  build() {
    Column()
      .flex(1)
      .backgroundColor('#f5f7fa')
      .safeArea(true) {
      
      // 头部
      Row()
        .justifyContent(FlexAlign.SpaceBetween)
        .alignItems(ItemAlign.Center)
        .padding(16)
        .backgroundColor('#ffffff')
        .borderBottom({ width: 1, color: '#e2e8f0' }) {
        Text('支付订单')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#1e293b');
        
        Text(`订单号: ${this.orderInfo.orderId}`)
          .fontSize(12)
          .fontColor('#64748b');
      }
      
      // 滚动内容区
      Scroll()
        .flex(1)
        .marginTop(12) {
        Column() {
          // 订单摘要
          Column()
            .backgroundColor('#ffffff')
            .marginLeft(16)
            .marginRight(16)
            .marginBottom(12)
            .borderRadius(12)
            .padding(16)
            .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
            
            Text('订单摘要')
              .fontSize(16)
              .fontWeight(FontWeight.Medium)
              .fontColor('#1e293b')
              .marginBottom(12);
            
            // 商品数量
            Row()
              .justifyContent(FlexAlign.SpaceBetween)
              .paddingVertical(6) {
              Text('商品数量')
                .fontSize(14)
                .fontColor('#64748b');
              
              Text(`${this.orderInfo.items}`)
                .fontSize(14)
                .fontColor('#1e293b');
            }
            
            // 商品金额
            Row()
              .justifyContent(FlexAlign.SpaceBetween)
              .paddingVertical(6) {
              Text('商品金额')
                .fontSize(14)
                .fontColor('#64748b');
              
              Text(`¥${this.orderInfo.amount}`)
                .fontSize(14)
                .fontColor('#1e293b');
            }
            
            // 运费
            Row()
              .justifyContent(FlexAlign.SpaceBetween)
              .paddingVertical(6) {
              Text('运费')
                .fontSize(14)
                .fontColor('#64748b');
              
              Text('¥0')
                .fontSize(14)
                .fontColor('#1e293b');
            }
            
            // 应付总额
            Row()
              .justifyContent(FlexAlign.SpaceBetween)
              .paddingTop(12)
              .marginTop(12)
              .borderTop({ width: 1, color: '#e2e8f0' }) {
              Text('应付总额')
                .fontSize(16)
                .fontColor('#1e293b')
                .fontWeight(FontWeight.Bold);
              
              Text(`¥${this.orderInfo.amount}`)
                .fontSize(18)
                .fontColor('#ef4444')
                .fontWeight(FontWeight.Bold);
            }
          }
          
          // 支付方式选择
          Column()
            .backgroundColor('#ffffff')
            .marginLeft(16)
            .marginRight(16)
            .marginBottom(12)
            .borderRadius(12)
            .padding(16)
            .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
            
            Text('选择支付方式')
              .fontSize(16)
              .fontWeight(FontWeight.Medium)
              .fontColor('#1e293b')
              .marginBottom(12);
            
            // 支付方式列表
            ForEach(this.paymentMethods, (method: PaymentMethod) => {
              Button()
                .backgroundColor(this.selectedMethod === method.id ? '#eff6ff' : '#f8fafc')
                .border({ 
                  width: this.selectedMethod === method.id ? 1 : 0, 
                  color: '#3b82f6' 
                })
                .borderRadius(8)
                .padding(12)
                .marginBottom(8)
                .onClick(() => this.selectedMethod = method.id) {
              
              Row()
                .alignItems(ItemAlign.Center) {
                // 支付方式内容区
                Row()
                  .alignItems(ItemAlign.Center)
                  .flex(1) {
                  Text(method.icon)
                    .fontSize(24)
                    .marginRight(12);
                  
                  Column()
                    .flex(1) {
                    Text(method.name)
                      .fontSize(16)
                      .fontWeight(FontWeight.Medium)
                      .fontColor('#1e293b')
                      .marginBottom(4);
                    
                    Text(method.description)
                      .fontSize(14)
                      .fontColor('#64748b');
                  }
                  
                  // 手续费提示
                  if (method.fee && method.fee > 0) {
                    Text(`${method.fee}`)
                      .fontSize(14)
                      .fontColor('#ef4444')
                      .fontWeight(FontWeight.Medium);
                  }
                }
                
                // 选中标记
                if (this.selectedMethod === method.id) {
                  Text('✅')
                    .fontSize(20)
                    .fontColor('#3b82f6');
                }
              }
            }
            }, (method: PaymentMethod) => method.id)
          }
          
          // 安全提示
          Column()
            .backgroundColor('#ffffff')
            .marginLeft(16)
            .marginRight(16)
            .marginBottom(12)
            .borderRadius(12)
            .padding(16)
            .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
            
            Text('安全提示')
              .fontSize(16)
              .fontWeight(FontWeight.Medium)
              .fontColor('#1e293b')
              .marginBottom(12);
            
            Text('• 本平台采用SSL加密传输,保障交易安全')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22)
              .marginBottom(4);
            
            Text('• 请确认支付金额与订单金额一致')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22)
              .marginBottom(4);
            
            Text('• 如遇到支付问题,请联系客服')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22);
          }
          
          // 协议确认
          Column()
            .backgroundColor('#ffffff')
            .marginLeft(16)
            .marginRight(16)
            .marginBottom(12)
            .borderRadius(12)
            .padding(16)
            .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
            
            Row()
              .alignItems(ItemAlign.Center)
              .onClick(() => this.agreed = !this.agreed) {
              
              // 自定义复选框
              Stack()
                .width(20)
                .height(20)
                .borderRadius(10)
                .border({ width: 2, color: this.agreed ? '#3b82f6' : '#cbd5e1' })
                .backgroundColor(this.agreed ? '#3b82f6' : Color.Transparent)
                .marginRight(12) {
                if (this.agreed) {
                  Text('✓')
                    .fontColor('#ffffff')
                    .fontSize(14)
                    .fontWeight(FontWeight.Bold)
                    .alignSelf(ItemAlign.Center);
                }
              }
              
              // 协议文本
              Text('我已阅读并同意 ')
                .fontSize(14)
                .fontColor('#64748b')
                .append(
                  Text('《支付协议》')
                    .fontColor('#3b82f6'),
                  Text(' 和 '),
                  Text('《隐私政策》')
                    .fontColor('#3b82f6')
                )
                .flex(1);
            }
          }
          
          // 支付倒计时
          Column()
            .backgroundColor('#fffbeb')
            .marginLeft(16)
            .marginRight(16)
            .marginBottom(80)
            .borderRadius(12)
            .padding(16)
            .alignItems(ItemAlign.Center)
            .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
            
            Text('支付倒计时')
              .fontSize(16)
              .fontWeight(FontWeight.Medium)
              .fontColor('#1e293b')
              .marginBottom(8);
            
            Text('00:15:00')
              .fontSize(24)
              .fontWeight(FontWeight.Bold)
              .fontColor('#f59e0b')
              .marginBottom(4);
            
            Text('请在规定时间内完成支付')
              .fontSize(14)
              .fontColor('#f59e0b');
          }
        }
      }
      
      // 底部支付栏
      Row()
        .alignItems(ItemAlign.Center)
        .justifyContent(FlexAlign.SpaceBetween)
        .padding(16)
        .backgroundColor('#ffffff')
        .borderTop({ width: 1, color: '#e2e8f0' })
        .position(Position.Fixed)
        .bottom(60)
        .width('100%') {
        
        // 实付金额
        Row()
          .alignItems(ItemAlign.Center) {
          Text('实付金额:')
            .fontSize(16)
            .fontColor('#1e293b')
            .marginRight(8);
          
          Text(`¥${this.orderInfo.amount + (this.paymentMethods.find(m => m.id === this.selectedMethod)?.fee || 0)}`)
            .fontSize(20)
            .fontColor('#ef4444')
            .fontWeight(FontWeight.Bold);
        }
        
        // 支付按钮
        Button()
          .backgroundColor('#3b82f6')
          .paddingLeft(24)
          .paddingRight(24)
          .paddingTop(12)
          .paddingBottom(12)
          .borderRadius(6)
          .onClick(() => this.handlePayment()) {
          Text('立即支付')
            .fontColor('#ffffff')
            .fontSize(16)
            .fontWeight(FontWeight.Medium);
        }
      }
      
      // 底部导航
      Row()
        .justifyContent(FlexAlign.SpaceAround)
        .backgroundColor('#ffffff')
        .borderTop({ width: 1, color: '#e2e8f0' })
        .paddingTop(12)
        .paddingBottom(12)
        .position(Position.Fixed)
        .bottom(0)
        .width('100%') {
        
        // 首页
        Column()
          .alignItems(ItemAlign.Center)
          .flex(1) {
          Text('🏠')
            .fontSize(20)
            .fontColor('#94a3b8')
            .marginBottom(4);
          Text('首页')
            .fontSize(12)
            .fontColor('#94a3b8');
        }
        
        // 分类
        Column()
          .alignItems(ItemAlign.Center)
          .flex(1) {
          Text('🔍')
            .fontSize(20)
            .fontColor('#94a3b8')
            .marginBottom(4);
          Text('分类')
            .fontSize(12)
            .fontColor('#94a3b8');
        }
        
        // 购物车
        Column()
          .alignItems(ItemAlign.Center)
          .flex(1) {
          Text('🛒')
            .fontSize(20)
            .fontColor('#94a3b8')
            .marginBottom(4);
          Text('购物车')
            .fontSize(12)
            .fontColor('#94a3b8');
        }
        
        // 我的(当前页)
        Column()
          .alignItems(ItemAlign.Center)
          .flex(1)
          .paddingTop(4)
          .borderTop({ width: 2, color: '#3b82f6' }) {
          Text('👤')
            .fontSize(20)
            .fontColor('#3b82f6')
            .marginBottom(4);
          Text('我的')
            .fontSize(12)
            .fontColor('#3b82f6')
            .fontWeight(FontWeight.Medium);
        }
      }
    }
  }
}

React Native 特性 鸿蒙 ArkUI 对应实现 适配关键说明
useState @State 装饰器 状态初始化与更新逻辑完全复用,仅调整语法形式
FlatList/map ForEach 组件 支付方式列表渲染逻辑对等,均通过唯一 key 提升性能
TouchableOpacity Button + onClick 所有可点击组件通过 Button 或 onClick 事件实现
ScrollView Scroll 组件 滚动容器语法差异,功能完全一致
Alert.alert AlertDialog.show 弹窗 API 语法差异,功能对等,支持取消/确认按钮
StyleSheet 链式样式 样式属性(颜色、间距、圆角等)完全复用
Position: 'absolute' Position.Fixed 绝对定位属性语法差异,底部栏定位效果一致
keyExtractor ForEach 第三个参数 均通过唯一 key 提升列表渲染性能
filter/map/find 数组方法 支付金额计算/支付方式查找的数组方法完全复用
SafeAreaView safeArea(true) 安全区域适配语法差异,效果一致
条件渲染 && if 语句 手续费、选中标记等条件渲染逻辑对等实现
自定义复选框 Stack 组件 通过 Stack 组合 View + Text 实现自定义复选框,样式一致

  • RN 端优化策略
    • 使用数组 map 渲染支付方式列表,结合 keyExtractor 提升渲染性能;
    • 静态数据使用 const [x] = useState() 声明,避免不必要的重渲染;
    • 底部栏使用绝对定位,避免滚动时重渲染;
    • 条件渲染仅展示必要信息,减少 DOM 节点数量。
  • 鸿蒙端优化策略
    • 使用 ForEach 渲染支付方式列表,通过唯一 key 提升渲染性能;
    • 自定义复选框使用 Stack 组件,减少嵌套层级;
    • 底部栏使用 Position.Fixed 固定定位,避免滚动时重渲染;
    • 协议文本使用 append 方法拼接,避免多 Text 组件嵌套;
    • onClick 事件中直接更新状态,避免中间变量。

  • 数据层完全复用:PaymentMethod/OrderInfo 数据模型字段完全一致,仅调整 TypeScript/ArkTS 类型定义语法;
  • 业务逻辑对等实现:支付校验、金额计算、支付流程等核心逻辑100%复用;
  • 交互体验统一:支付方式选择、协议确认、金额展示等交互细节保持一致;
  • 视觉体验一致:复用相同的色彩体系、间距规范、圆角大小、字体层级;
  • 金额计算精准:实付金额 = 订单金额 + 支付手续费的计算逻辑完全一致;
  • 布局架构镜像:保持“头部-内容区-底部支付栏-底部导航”的核心布局结构;
  • 合规性一致:协议确认、安全提示等合规性设计跨端保持一致。

  1. 支付订单页核心是金额精准 + 流程合规:订单金额、手续费、实付金额的精准计算,以及协议确认、安全提示等合规性设计,是跨端适配的核心;
  2. 状态管理需精准映射用户选择:支付方式、协议同意状态的选择,需保证跨端的一致性和实时性;
  3. 交互体验需符合支付场景习惯:支付确认弹窗、金额突出展示、底部固定支付按钮等设计,需遵循支付场景的交互规范;
  4. 金额计算是核心保障:实付金额的计算逻辑需100%精准,避免跨端金额不一致;
  5. 合规性设计不可忽视:协议确认、安全提示、订单号展示等合规性设计,是支付场景的必备要素。

React Native 支付订单应用的跨端适配实践,验证了 ArkTS 与 React 技术体系在电商支付场景下的高度兼容性。对于支付这类以金额精准计算-合规性交互-安全提示为核心的场景,90% 以上的业务逻辑和数据模型均可实现跨端复用,仅需适配平台特有 API 和布局语法,是跨端电商应用开发的高效路径。


真实演示案例代码:





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

// Base64 图标库
const ICONS_BASE64 = {
  creditCard: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  alipay: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  wechatPay: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  bankTransfer: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  check: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  clock: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  security: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  home: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};

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

// 支付方式类型
type PaymentMethod = {
  id: string;
  name: string;
  icon: string;
  description: string;
  fee?: number;
};

// 订单信息类型
type OrderInfo = {
  orderId: string;
  amount: number;
  items: number;
  status: 'pending' | 'paid' | 'cancelled';
};

// 支付应用组件
const PaymentApp: React.FC = () => {
  const [orderInfo] = useState<OrderInfo>({
    orderId: 'ORD202310120001',
    amount: 18497,
    items: 3,
    status: 'pending'
  });

  const [paymentMethods] = useState<PaymentMethod[]>([
    { id: 'alipay', name: '支付宝', icon: '💳', description: '使用支付宝支付', fee: 0 },
    { id: 'wechat', name: '微信支付', icon: '💬', description: '使用微信支付', fee: 0 },
    { id: 'credit', name: '信用卡', icon: '💳', description: '使用信用卡支付', fee: 5 },
    { id: 'debit', name: '借记卡', icon: '💳', description: '使用借记卡支付', fee: 0 },
    { id: 'bank', name: '银行转账', icon: '🏦', description: '使用银行转账', fee: 2 },
  ]);

  const [selectedMethod, setSelectedMethod] = useState<string>('alipay');
  const [agreed, setAgreed] = useState<boolean>(true);

  const handlePayment = () => {
    if (!agreed) {
      Alert.alert('提示', '请同意支付协议');
      return;
    }

    const method = paymentMethods.find(m => m.id === selectedMethod);
    Alert.alert(
      '支付确认',
      `您选择使用${method?.name}支付 ¥${orderInfo.amount + (method?.fee || 0)}\n\n订单号: ${orderInfo.orderId}`,
      [
        {
          text: '取消',
          style: 'cancel'
        },
        {
          text: '确认支付',
          onPress: () => {
            // 模拟支付过程
            Alert.alert(
              '支付成功',
              '您的订单已支付成功!\n\n订单号: ORD202310120001',
              [
                {
                  text: '确定',
                  onPress: () => console.log('支付完成')
                }
              ]
            );
          }
        }
      ]
    );
  };

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <Text style={styles.title}>支付订单</Text>
        <Text style={styles.orderId}>订单号: {orderInfo.orderId}</Text>
      </View>

      <ScrollView style={styles.content}>
        {/* 订单摘要 */}
        <View style={styles.orderSummary}>
          <Text style={styles.summaryTitle}>订单摘要</Text>
          <View style={styles.summaryRow}>
            <Text style={styles.summaryLabel}>商品数量</Text>
            <Text style={styles.summaryValue}>{orderInfo.items}</Text>
          </View>
          <View style={styles.summaryRow}>
            <Text style={styles.summaryLabel}>商品金额</Text>
            <Text style={styles.summaryValue}>¥{orderInfo.amount}</Text>
          </View>
          <View style={styles.summaryRow}>
            <Text style={styles.summaryLabel}>运费</Text>
            <Text style={styles.summaryValue}>¥0</Text>
          </View>
          <View style={styles.totalRow}>
            <Text style={styles.totalLabel}>应付总额</Text>
            <Text style={styles.totalValue}>¥{orderInfo.amount}</Text>
          </View>
        </View>

        {/* 支付方式选择 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>选择支付方式</Text>
          {paymentMethods.map(method => (
            <TouchableOpacity
              key={method.id}
              style={[
                styles.paymentOption,
                selectedMethod === method.id && styles.selectedPaymentOption
              ]}
              onPress={() => setSelectedMethod(method.id)}
            >
              <View style={styles.paymentOptionContent}>
                <Text style={styles.paymentIcon}>{method.icon}</Text>
                <View style={styles.paymentInfo}>
                  <Text style={styles.paymentName}>{method.name}</Text>
                  <Text style={styles.paymentDescription}>{method.description}</Text>
                </View>
                {method.fee && method.fee > 0 && (
                  <Text style={styles.feeText}>+¥{method.fee}</Text>
                )}
              </View>
              {selectedMethod === method.id && (
                <Text style={styles.checkIcon}></Text>
              )}
            </TouchableOpacity>
          ))}
        </View>

        {/* 安全提示 */}
        <View style={styles.securityCard}>
          <Text style={styles.securityTitle}>安全提示</Text>
          <Text style={styles.securityText}>• 本平台采用SSL加密传输,保障交易安全</Text>
          <Text style={styles.securityText}>• 请确认支付金额与订单金额一致</Text>
          <Text style={styles.securityText}>• 如遇到支付问题,请联系客服</Text>
        </View>

        {/* 协议确认 */}
        <View style={styles.agreementSection}>
          <TouchableOpacity 
            style={styles.checkboxContainer}
            onPress={() => setAgreed(!agreed)}
          >
            <View style={[styles.checkbox, agreed && styles.checkboxChecked]}>
              {agreed && <Text style={styles.checkboxCheck}></Text>}
            </View>
            <Text style={styles.agreementText}>
              我已阅读并同意 <Text style={styles.linkText}>《支付协议》</Text><Text style={styles.linkText}>《隐私政策》</Text>
            </Text>
          </TouchableOpacity>
        </View>

        {/* 支付倒计时 */}
        <View style={styles.countdownCard}>
          <Text style={styles.countdownTitle}>支付倒计时</Text>
          <Text style={styles.countdownText}>00:15:00</Text>
          <Text style={styles.countdownDescription}>请在规定时间内完成支付</Text>
        </View>
      </ScrollView>

      {/* 底部支付按钮 */}
      <View style={styles.bottomBar}>
        <View style={styles.finalAmount}>
          <Text style={styles.finalAmountLabel}>实付金额:</Text>
          <Text style={styles.finalAmountValue}>
            ¥{orderInfo.amount + (paymentMethods.find(m => m.id === selectedMethod)?.fee || 0)}
          </Text>
        </View>
        <TouchableOpacity 
          style={styles.payButton} 
          onPress={handlePayment}
        >
          <Text style={styles.payButtonText}>立即支付</Text>
        </TouchableOpacity>
      </View>

      {/* 底部导航 */}
      <View style={styles.bottomNav}>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🏠</Text>
          <Text style={styles.navText}>首页</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🔍</Text>
          <Text style={styles.navText}>分类</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🛒</Text>
          <Text style={styles.navText}>购物车</Text>
        </TouchableOpacity>
        <TouchableOpacity style={[styles.navItem, styles.activeNavItem]}>
          <Text style={styles.navIcon}>👤</Text>
          <Text style={styles.navText}>我的</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f7fa',
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: 16,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  orderId: {
    fontSize: 12,
    color: '#64748b',
  },
  content: {
    flex: 1,
    marginTop: 12,
  },
  orderSummary: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  summaryTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  summaryRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingVertical: 6,
  },
  summaryLabel: {
    fontSize: 14,
    color: '#64748b',
  },
  summaryValue: {
    fontSize: 14,
    color: '#1e293b',
  },
  totalRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingTop: 12,
    marginTop: 12,
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
  },
  totalLabel: {
    fontSize: 16,
    color: '#1e293b',
    fontWeight: 'bold',
  },
  totalValue: {
    fontSize: 18,
    color: '#ef4444',
    fontWeight: 'bold',
  },
  section: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  paymentOption: {
    backgroundColor: '#f8fafc',
    borderRadius: 8,
    padding: 12,
    marginBottom: 8,
  },
  selectedPaymentOption: {
    backgroundColor: '#eff6ff',
    borderColor: '#3b82f6',
    borderWidth: 1,
  },
  paymentOptionContent: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  paymentIcon: {
    fontSize: 24,
    marginRight: 12,
  },
  paymentInfo: {
    flex: 1,
  },
  paymentName: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 4,
  },
  paymentDescription: {
    fontSize: 14,
    color: '#64748b',
  },
  feeText: {
    fontSize: 14,
    color: '#ef4444',
    fontWeight: '500',
  },
  checkIcon: {
    fontSize: 20,
    color: '#3b82f6',
  },
  securityCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  securityTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  securityText: {
    fontSize: 14,
    color: '#64748b',
    lineHeight: 22,
    marginBottom: 4,
  },
  agreementSection: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  checkbox: {
    width: 20,
    height: 20,
    borderRadius: 10,
    borderWidth: 2,
    borderColor: '#cbd5e1',
    alignItems: 'center',
    justifyContent: 'center',
    marginRight: 12,
  },
  checkboxChecked: {
    backgroundColor: '#3b82f6',
    borderColor: '#3b82f6',
  },
  checkboxCheck: {
    color: '#ffffff',
    fontSize: 14,
    fontWeight: 'bold',
  },
  agreementText: {
    fontSize: 14,
    color: '#64748b',
    flex: 1,
  },
  linkText: {
    color: '#3b82f6',
  },
  countdownCard: {
    backgroundColor: '#fffbeb',
    marginHorizontal: 16,
    marginBottom: 80,
    borderRadius: 12,
    padding: 16,
    alignItems: 'center',
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  countdownTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 8,
  },
  countdownText: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#f59e0b',
    marginBottom: 4,
  },
  countdownDescription: {
    fontSize: 14,
    color: '#f59e0b',
  },
  bottomBar: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: 16,
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    position: 'absolute',
    bottom: 60,
    left: 0,
    right: 0,
  },
  finalAmount: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  finalAmountLabel: {
    fontSize: 16,
    color: '#1e293b',
    marginRight: 8,
  },
  finalAmountValue: {
    fontSize: 20,
    color: '#ef4444',
    fontWeight: 'bold',
  },
  payButton: {
    backgroundColor: '#3b82f6',
    paddingHorizontal: 24,
    paddingVertical: 12,
    borderRadius: 6,
  },
  payButtonText: {
    color: '#ffffff',
    fontSize: 16,
    fontWeight: '500',
  },
  bottomNav: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    paddingVertical: 12,
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
  },
  navItem: {
    alignItems: 'center',
    flex: 1,
  },
  activeNavItem: {
    paddingTop: 4,
    borderTopWidth: 2,
    borderTopColor: '#3b82f6',
  },
  navIcon: {
    fontSize: 20,
    color: '#94a3b8',
    marginBottom: 4,
  },
  activeNavIcon: {
    color: '#3b82f6',
  },
  navText: {
    fontSize: 12,
    color: '#94a3b8',
  },
  activeNavText: {
    color: '#3b82f6',
    fontWeight: '500',
  },
});

export default PaymentApp;

请添加图片描述


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述
本文深入分析了一个基于React Native实现的电商支付系统,从架构设计、数据模型和状态管理三个维度进行技术拆解。系统采用TypeScript构建了完整的支付数据模型(PaymentMethod和OrderInfo),通过React Hooks实现轻量级状态管理,支持支付方式选择、订单展示和支付处理等核心功能。设计上注重类型安全、扩展性和跨端兼容性,为鸿蒙系统适配预留了技术方案。该实现不仅功能完整,还通过模块化代码组织和响应式交互设计,为用户提供了流畅的支付体验,为跨端电商支付场景开发提供了可参考的技术实践。

Logo

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

更多推荐