在电商应用中,订单修改功能是提升用户体验、增加订单灵活性的重要功能。本文将深入分析一个基于 React Native 实现的订单修改与取消系统,探讨其架构设计、技术实现以及鸿蒙跨端适配策略。

核心数据

该系统构建了清晰的订单数据模型,为订单修改提供了完整的数据支持:

// 订单状态类型
type OrderStatus = 'pending-payment' | 'pending-delivery' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';

// 订单项目类型
type OrderItem = {
  id: string;
  name: string;
  price: number;
  quantity: number;
  image: string;
};

// 订单类型
type Order = {
  id: string;
  orderNumber: string;
  date: string;
  status: OrderStatus;
  totalAmount: number;
  items: OrderItem[];
  shippingAddress: {
    name: string;
    phone: string;
    address: string;
  };
  paymentMethod: string;
};

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

  • 类型安全:使用 TypeScript 联合类型定义订单状态,确保状态值的合法性
  • 完整性:涵盖了订单的所有核心属性,包括订单状态、商品、地址等
  • 层级清晰:订单包含商品列表和地址对象,结构层次分明
  • 扩展性:支持添加更多属性,如物流信息、订单备注等

状态管理

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

const [order] = useState<Order>({
  // 订单数据...
});

const [newAddress, setNewAddress] = useState({
  name: order.shippingAddress.name,
  phone: order.shippingAddress.phone,
  address: order.shippingAddress.address
});

const [editingField, setEditingField] = useState<string | null>(null);

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

  • 模块化:将订单数据、新地址数据和编辑状态分离管理,提高代码可读性
  • 响应式:状态变更自动触发组件重渲染,确保 UI 与数据同步
  • 跨端兼容:React Hooks 在鸿蒙系统的 React Native 实现中通常都有良好支持
  • 灵活性:支持就地编辑模式,提高用户体验

系统实现了完整的订单修改功能,包括:

地址修改权限

系统根据订单状态判断是否可以修改收货地址:

const canModifyAddress = (): boolean => {
  return order.status === 'pending-payment' || order.status === 'pending-delivery';
};

只有在订单待付款或待发货状态下,用户才能修改收货地址,这符合电商平台的常见规则。

订单取消权限

系统根据订单状态判断是否可以取消订单:

const canCancelOrder = (): boolean => {
  return order.status === 'pending-payment' || order.status === 'pending-delivery';
};

同样,只有在订单待付款或待发货状态下,用户才能取消订单,一旦订单发货,就不能再取消。

地址修改

系统实现了就地编辑模式的地址修改功能:

  • 点击编辑按钮进入编辑模式
  • 在编辑模式下修改收货人、电话和地址
  • 保存修改时进行表单验证,确保信息完整
  • 显示确认对话框,避免误操作
  • 保存成功后显示提示信息

基础架构

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

  • SafeAreaView:适配刘海屏等异形屏
  • ScrollView:处理内容滚动,确保长页面可浏览
  • TouchableOpacity:提供触摸反馈,增强用户体验
  • TextInput:提供文本输入功能,支持地址修改
  • TextView:构建基本 UI 结构
  • Alert:系统级弹窗提示,提供操作反馈

Base64 图标

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

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

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

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

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

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

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

通过地址修改、订单取消、权限控制等核心功能,结合 Base64 图标处理、就地编辑模式等技术手段,该系统不仅功能完善,而且具有良好的可维护性和可扩展性。这些实践经验对于构建其他跨端应用组件也具有参考价值。


订单修改是电商应用中高频且核心的交互场景,承载着收货地址编辑、订单取消、状态权限控制三大核心诉求。本文将从类型系统设计、状态驱动交互、权限控制逻辑三个维度深度拆解这份 React Native 订单修改页面代码,并提供完整的鸿蒙(HarmonyOS)ArkTS 跨端适配方案,为跨端电商订单操作模块开发提供可落地的技术参考。

1. 强类型

订单修改场景的核心是状态驱动的权限控制,代码通过 TypeScript 构建了精准匹配业务规则的类型体系,从底层约束订单状态的合法取值范围:

// 订单状态联合类型:显式约束所有合法状态值
type OrderStatus = 'pending-payment' | 'pending-delivery' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';

// 订单项目类型:标准化商品信息结构
type OrderItem = {
  id: string;
  name: string;
  price: number;
  quantity: number;
  image: string;
};

// 订单主类型:聚合所有核心字段
type Order = {
  id: string;
  orderNumber: string;
  date: string;
  status: OrderStatus; // 强类型约束状态字段
  totalAmount: number;
  items: OrderItem[];
  shippingAddress: {
    name: string;
    phone: string;
    address: string;
  };
  paymentMethod: string;
};

类型设计亮点解析

  • 状态枚举化:使用 TypeScript 联合类型 OrderStatus 显式定义所有合法的订单状态,杜绝非法状态值的传入,从编译层面保证状态逻辑的正确性;
  • 地址结构化:将收货地址封装为嵌套对象,便于地址信息的整体管理和批量修改;
  • 商品列表标准化OrderItem 类型覆盖商品展示的核心维度,为后续商品信息渲染提供统一规范;
  • 类型约束下沉:将 status 字段的类型约束直接关联到 Order 类型中,确保整个订单对象的类型安全性。

2. 状态驱动

订单修改页面的核心交互是收货地址的编辑/展示状态切换,代码通过 React 的 useState 实现了状态的精细化管理,保证交互的流畅性和数据的一致性:

// 地址编辑状态管理
const [newAddress, setNewAddress] = useState({
  name: order.shippingAddress.name,
  phone: order.shippingAddress.phone,
  address: order.shippingAddress.address
});

// 编辑字段控制:精准控制当前是否处于编辑状态
const [editingField, setEditingField] = useState<string | null>(null);
(1)权限控制函数

订单修改的核心业务规则是不同状态下的操作权限差异,代码将权限判断逻辑封装为独立函数,提升代码的可读性和复用性:

// 判断是否可修改地址:仅待付款/待发货订单可修改
const canModifyAddress = (): boolean => {
  return order.status === 'pending-payment' || order.status === 'pending-delivery';
};

// 判断是否可取消订单:仅待付款/待发货订单可取消
const canCancelOrder = (): boolean => {
  return order.status === 'pending-payment' || order.status === 'pending-delivery';
};

权限设计亮点

  • 规则集中管理:将权限判断逻辑从渲染逻辑中抽离,避免在 JSX 中嵌入复杂的条件判断,提升代码可维护性;
  • 返回值标准化:统一返回布尔值,便于在渲染逻辑中直接使用;
  • 业务规则清晰:函数命名直观反映业务意图,新人接手时可快速理解权限规则;
  • 扩展便捷:新增权限规则时仅需修改函数内部逻辑,无需改动渲染代码。
(2)地址编辑流程

收货地址修改是核心操作,代码实现了从编辑-校验-确认-保存的完整流程,兼顾用户体验和数据安全性:

const handleSaveAddress = () => {
  // 1. 表单校验:确保必填字段完整
  if (!newAddress.name || !newAddress.phone || !newAddress.address) {
    Alert.alert('提示', '请填写完整的收货信息');
    return;
  }

  // 2. 二次确认:防止误操作
  Alert.alert(
    '确认修改',
    '您确定要修改收货地址吗?',
    [
      { text: '取消', style: 'cancel' },
      {
        text: '确定',
        onPress: () => {
          // 3. 操作反馈:告知用户修改结果
          Alert.alert('成功', '收货地址已修改成功');
          // 4. 状态重置:退出编辑态
          setEditingField(null);
        }
      }
    ]
  );
};

流程设计亮点

  • 前置校验:在提交前进行必填字段校验,避免无效的接口请求;
  • 二次确认:对重要操作添加确认弹窗,降低误操作概率;
  • 操作反馈:明确告知用户操作结果,提升交互的确定性;
  • 状态重置:操作完成后自动退出编辑状态,恢复展示态。
(3)订单取消:

订单取消属于高风险操作,代码在流程设计上更加谨慎,强化了风险提示:

const handleCancelOrder = () => {
  Alert.alert(
    '取消订单',
    '您确定要取消此订单吗?取消后订单将无法恢复。', // 风险提示
    [
      { text: '取消', style: 'cancel' },
      {
        text: '确定',
        onPress: () => {
          Alert.alert('成功', '订单已取消');
        }
      }
    ]
  );
};

风险控制亮点

  • 明确的风险提示:在确认弹窗中明确告知用户“取消后订单将无法恢复”,提升用户的操作认知;
  • 操作不可逆提示:强化用户对操作后果的理解,避免误取消;
  • 反馈明确:操作完成后给出清晰的成功提示。

订单修改页面的 UI 设计核心是根据订单状态和编辑状态动态调整渲染内容,代码通过条件渲染实现了不同状态下的界面适配:

(1)地址编辑/展示态切换

核心实现逻辑是通过 editingField 状态控制渲染内容,编辑态展示表单,展示态展示地址信息:

{editingField === 'address' ? (
  // 编辑态:展示地址编辑表单
  <View style={styles.editForm}>
    {/* 姓名输入框 */}
    {/* 电话输入框 */}
    {/* 地址输入框 */}
    {/* 取消/保存按钮 */}
  </View>
) : (
  // 展示态:展示地址信息
  <View style={styles.addressInfo}>
    {/* 地址信息展示 */}
    {canModifyAddress() && (
      <TouchableOpacity 
        style={styles.editButton}
        onPress={() => setEditingField('address')}
      >
        <Text style={styles.editButtonText}>修改地址</Text>
      </TouchableOpacity>
    )}
  </View>
)}

UI 切换亮点

  • 状态驱动渲染:通过单一状态变量控制整个地址模块的渲染形态,逻辑清晰;
  • 权限感知渲染:仅在可修改地址时展示“修改地址”按钮,避免无效操作入口;
  • 表单体验优化:地址输入框使用多行文本框(multiline),并设置 textAlignVertical: 'top',提升长地址输入体验;
  • 输入框样式统一:所有输入框使用一致的边框、内边距和背景色,保证视觉统一性。
(2)操作按钮

根据订单状态动态展示可操作按钮,不可操作时展示禁用状态:

{canCancelOrder() ? (
  <TouchableOpacity 
    style={styles.cancelOrderButton}
    onPress={handleCancelOrder}
  >
    <Text style={styles.cancelOrderButtonText}>取消订单</Text>
  </TouchableOpacity>
) : (
  <View style={styles.disabledButton}>
    <Text style={styles.disabledButtonText}>无法取消订单</Text>
  </View>
)}

按钮设计亮点

  • 视觉区分明显:可取消时展示红色按钮(警示色),不可取消时展示灰色禁用按钮;
  • 交互反馈合理:禁用状态使用普通 View 而非 disabled 的 TouchableOpacity,避免用户点击无反馈;
  • 文案适配:禁用状态的文案明确告知用户“无法取消订单”,而非简单的置灰;
  • 操作入口统一:无论是否可操作,都保留按钮占位,避免界面布局跳动。

代码通过 StyleSheet.create 构建了符合电商场景的样式体系,核心设计原则包括:

  • 卡片式布局统一:所有功能模块使用相同的卡片样式(白色背景、12px 圆角、轻微阴影),保证视觉一致性;
  • 间距规范:卡片内边距 16px,卡片间距 12px,输入框间距 16px,形成统一的间距体系;
  • 色彩语义化
    • 取消订单按钮使用红色(#ef4444):警示操作
    • 保存按钮使用蓝色(#3b82f6):主要操作
    • 取消按钮使用灰色(#f1f5f9):次要操作
    • 禁用按钮使用浅灰色(#cbd5e1):不可操作
  • 文字层级清晰:通过字体大小(20/18/16/14/12px)和字重(bold/500/normal)区分信息优先级;
  • 表单样式统一:所有输入框使用相同的边框、内边距和圆角,提升表单填写体验;
  • 底部导航固定:使用绝对定位将底部导航固定在页面底部,保证导航的可访问性。

将 React Native 订单修改页面迁移至鸿蒙平台,核心是基于 ArkTS + ArkUI 实现类型系统、状态管理、权限控制、动态渲染的对等还原,同时适配鸿蒙的组件特性和布局范式。

1. 核心

鸿蒙端的适配遵循逻辑复用、语法适配、体验统一的原则,90%以上的业务逻辑和视觉规范可直接复用,仅需适配平台特有 API 和组件语法:

@Entry
@Component
struct OrderModifyApp {
  // 数据模型:完全复用 RN 端字段定义
  @State order: Order = {/* 订单数据 */};
  // 地址编辑状态:对等实现
  @State newAddress: { name: string; phone: string; address: string } = {/* 地址数据 */};
  // 编辑状态控制:对等实现
  @State editingField: string | null = null;

  // 权限控制函数:完全复用 RN 端逻辑
  canModifyAddress(): boolean {
    return this.order.status === 'pending-payment' || this.order.status === 'pending-delivery';
  }

  canCancelOrder(): boolean {
    return this.order.status === 'pending-payment' || this.order.status === 'pending-delivery';
  }

  // 地址保存逻辑:对等实现(适配鸿蒙弹窗 API)
  handleSaveAddress() {
    // 表单校验逻辑(复用)
    // 确认弹窗(适配鸿蒙 AlertDialog API)
  }

  // 页面构建:镜像 RN 端布局结构
  build() {
    Column()
      .flex(1)
      .backgroundColor('#f5f7fa')
      .safeArea(true) {
      
      // 头部区域
      // 滚动内容区(包含所有卡片)
      // 底部导航区
    }
  }
}

React Native 特性 鸿蒙 ArkUI 对应实现 适配关键说明
useState @State 装饰器 状态初始化与更新逻辑完全复用,仅调整语法形式
TouchableOpacity Button + onClick 可点击组件的交互逻辑完全复用
Alert.alert AlertDialog.show 弹窗 API 语法差异,交互逻辑对等
StyleSheet 链式样式 样式属性(颜色、间距、圆角等)100% 复用
TextInput TextInput 组件 输入框属性(value、onChange、placeholder 等)完全复用
条件渲染 if/else 渲染 动态渲染逻辑完全复用,语法形式适配
ScrollView Scroll 组件 滚动容器语法差异,功能一致
reduce 数组方法 reduce 数组方法 数组操作逻辑完全复用
绝对定位 position: Position.Fixed 定位语法差异,效果一致

3. 鸿蒙代码

// 鸿蒙 ArkTS 完整实现
type OrderStatus = 'pending-payment' | 'pending-delivery' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';

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

type Order = {
  id: string;
  orderNumber: string;
  date: string;
  status: OrderStatus;
  totalAmount: number;
  items: OrderItem[];
  shippingAddress: {
    name: string;
    phone: string;
    address: string;
  };
  paymentMethod: string;
};

@Entry
@Component
struct OrderModifyApp {
  @State order: Order = {
    id: 'o1',
    orderNumber: 'ORD202310150001',
    date: '2023-10-15',
    status: 'pending-delivery',
    totalAmount: 10997,
    items: [
      { id: 'i1', name: 'iPhone 15 Pro Max', price: 9999, quantity: 1, image: 'https://via.placeholder.com/60x60' },
      { id: 'i2', name: '手机壳', price: 299, quantity: 1, image: 'https://via.placeholder.com/60x60' },
      { id: 'i3', name: '钢化膜', price: 699, quantity: 1, image: 'https://via.placeholder.com/60x60' }
    ],
    shippingAddress: {
      name: '张三',
      phone: '138****8888',
      address: '北京市朝阳区某某街道123号'
    },
    paymentMethod: '支付宝'
  };

  @State newAddress: { name: string; phone: string; address: string } = {
    name: '张三',
    phone: '138****8888',
    address: '北京市朝阳区某某街道123号'
  };

  @State editingField: string | null = null;

  canModifyAddress(): boolean {
    return this.order.status === 'pending-payment' || this.order.status === 'pending-delivery';
  }

  canCancelOrder(): boolean {
    return this.order.status === 'pending-payment' || this.order.status === 'pending-delivery';
  }

  handleSaveAddress() {
    if (!this.newAddress.name || !this.newAddress.phone || !this.newAddress.address) {
      AlertDialog.show({
        title: '提示',
        message: '请填写完整的收货信息',
        confirm: { value: '确定' }
      });
      return;
    }

    AlertDialog.show({
      title: '确认修改',
      message: '您确定要修改收货地址吗?',
      confirm: {
        value: '确定',
        action: () => {
          AlertDialog.show({
            title: '成功',
            message: '收货地址已修改成功',
            confirm: { value: '确定' }
          });
          this.editingField = null;
        }
      },
      cancel: { value: '取消' }
    });
  }

  handleCancelOrder() {
    AlertDialog.show({
      title: '取消订单',
      message: '您确定要取消此订单吗?取消后订单将无法恢复。',
      confirm: {
        value: '确定',
        action: () => {
          AlertDialog.show({
            title: '成功',
            message: '订单已取消',
            confirm: { value: '确定' }
          });
        }
      },
      cancel: { value: '取消' }
    });
  }

  getStatusText(status: OrderStatus): string {
    switch (status) {
      case 'pending-payment': return '待付款';
      case 'pending-delivery': return '待发货';
      case 'shipped': return '已发货';
      case 'delivered': return '已签收';
      case 'cancelled': return '已取消';
      case 'refunded': return '已退款';
      default: return '未知状态';
    }
  }

  getStatusColor(status: OrderStatus): string {
    switch (status) {
      case 'pending-payment': return '#f59e0b';
      case 'pending-delivery': return '#3b82f6';
      case 'shipped': return '#10b981';
      case 'delivered': return '#10b981';
      case 'cancelled': return '#9ca3af';
      case 'refunded': return '#8b5cf6';
      default: return '#9ca3af';
    }
  }

  build() {
    Column()
      .flex(1)
      .backgroundColor('#f5f7fa')
      .safeArea(true) {
      
      // 头部
      Column()
        .padding(16)
        .backgroundColor('#ffffff')
        .borderBottom({ width: 1, color: '#e2e8f0' }) {
        Text('订单修改')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#1e293b')
          .marginBottom(4);
        
        Text(`订单号: ${this.order.orderNumber}`)
          .fontSize(14)
          .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 }) {
            
            Row()
              .justifyContent(FlexAlign.SpaceBetween)
              .alignItems(ItemAlign.Center)
              .marginBottom(8) {
              Text(this.getStatusText(this.order.status))
                .fontSize(18)
                .fontWeight(FontWeight.Bold)
                .fontColor(this.getStatusColor(this.order.status));
            }
            
            Text(this.order.status === 'pending-delivery' 
              ? '订单尚未发货,您可以修改收货地址或取消订单' 
              : this.order.status === 'pending-payment'
              ? '订单尚未付款,您可以修改收货地址或取消订单'
              : '订单已发货,无法修改收货地址')
              .fontSize(14)
              .fontColor('#64748b');
          }

          // 收货地址卡片
          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);
            
            if (this.editingField === 'address') {
              // 编辑态
              Column() {
                // 姓名输入框
                Column()
                  .marginBottom(16) {
                  Text('收货人姓名')
                    .fontSize(14)
                    .fontColor('#64748b')
                    .marginBottom(4);
                  
                  TextInput({
                    value: this.newAddress.name,
                    placeholder: '请输入收货人姓名'
                  })
                    .border({ width: 1, color: '#e2e8f0' })
                    .borderRadius(6)
                    .padding(12)
                    .fontSize(16)
                    .backgroundColor('#f8fafc')
                    .onChange((value) => {
                      this.newAddress.name = value;
                    });
                }
                
                // 电话输入框
                Column()
                  .marginBottom(16) {
                  Text('联系电话')
                    .fontSize(14)
                    .fontColor('#64748b')
                    .marginBottom(4);
                  
                  TextInput({
                    value: this.newAddress.phone,
                    placeholder: '请输入联系电话'
                  })
                    .border({ width: 1, color: '#e2e8f0' })
                    .borderRadius(6)
                    .padding(12)
                    .fontSize(16)
                    .backgroundColor('#f8fafc')
                    .type(InputType.PhoneNumber)
                    .onChange((value) => {
                      this.newAddress.phone = value;
                    });
                }
                
                // 地址输入框
                Column()
                  .marginBottom(16) {
                  Text('详细地址')
                    .fontSize(14)
                    .fontColor('#64748b')
                    .marginBottom(4);
                  
                  TextInput({
                    value: this.newAddress.address,
                    placeholder: '请输入详细地址'
                  })
                    .border({ width: 1, color: '#e2e8f0' })
                    .borderRadius(6)
                    .padding(12)
                    .fontSize(16)
                    .backgroundColor('#f8fafc')
                    .height(80)
                    .multiline(true)
                    .onChange((value) => {
                      this.newAddress.address = value;
                    });
                }
                
                // 按钮组
                Row()
                  .justifyContent(FlexAlign.SpaceBetween)
                  .marginTop(16) {
                  Button()
                    .flexGrow(0.48)
                    .backgroundColor('#f1f5f9')
                    .paddingVertical(12)
                    .borderRadius(6)
                    .onClick(() => {
                      this.editingField = null;
                    }) {
                    Text('取消')
                      .fontSize(16)
                      .fontWeight(FontWeight.Medium)
                      .fontColor('#475569');
                  }
                  
                  Button()
                    .flexGrow(0.48)
                    .backgroundColor('#3b82f6')
                    .paddingVertical(12)
                    .borderRadius(6)
                    .onClick(() => {
                      this.handleSaveAddress();
                    }) {
                    Text('保存')
                      .fontSize(16)
                      .fontWeight(FontWeight.Medium)
                      .fontColor('#ffffff');
                  }
                }
              }
            } else {
              // 展示态
              Column()
                .padding(12)
                .backgroundColor('#f8fafc')
                .borderRadius(8) {
                Row()
                  .marginBottom(4) {
                  Text(this.newAddress.name)
                    .fontSize(14)
                    .fontWeight(FontWeight.Medium)
                    .fontColor('#1e293b')
                    .marginRight(12);
                  
                  Text(this.newAddress.phone)
                    .fontSize(14)
                    .fontColor('#64748b');
                }
                
                Text(this.newAddress.address)
                  .fontSize(14)
                  .fontColor('#64748b');
                
                if (this.canModifyAddress()) {
                  Button()
                    .marginTop(12)
                    .backgroundColor('#f1f5f9')
                    .paddingVertical(8)
                    .borderRadius(6)
                    .onClick(() => {
                      this.editingField = 'address';
                    }) {
                    Text('修改地址')
                      .fontSize(14)
                      .fontWeight(FontWeight.Medium)
                      .fontColor('#475569');
                  }
                }
              }
            }
          }

          // 订单商品卡片
          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.order.items, (item: OrderItem) => {
              Row()
                .alignItems(ItemAlign.Center)
                .marginBottom(12) {
                Column()
                  .flexGrow(1) {
                  Text(item.name)
                    .fontSize(14)
                    .fontColor('#1e293b')
                    .marginBottom(4);
                  
                  Text(`¥${item.price} x ${item.quantity}`)
                    .fontSize(12)
                    .fontColor('#64748b');
                }
              }
            }, (item: OrderItem) => item.id)
            
            Row()
              .justifyContent(FlexAlign.SpaceBetween)
              .alignItems(ItemAlign.Center)
              .marginTop(12)
              .paddingTop(12)
              .borderTop({ width: 1, color: '#e2e8f0' }) {
              Text(`商品总数: ${this.order.items.reduce((sum, item) => sum + item.quantity, 0)}`)
                .fontSize(14)
                .fontColor('#64748b');
              
              Text(`订单总额: ¥${this.order.totalAmount}`)
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .fontColor('#ef4444');
            }
          }

          // 订单信息卡片
          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)
              .marginBottom(8) {
              Text('下单时间:')
                .fontSize(14)
                .fontColor('#64748b')
                .flexGrow(0.4);
              
              Text(this.order.date)
                .fontSize(14)
                .fontColor('#1e293b')
                .flexGrow(0.6)
                .textAlign(TextAlign.Right);
            }
            
            Row()
              .justifyContent(FlexAlign.SpaceBetween) {
              Text('支付方式:')
                .fontSize(14)
                .fontColor('#64748b')
                .flexGrow(0.4);
              
              Text(this.order.paymentMethod)
                .fontSize(14)
                .fontColor('#1e293b')
                .flexGrow(0.6)
                .textAlign(TextAlign.Right);
            }
          }

          // 操作选项卡片
          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);
            
            if (this.canCancelOrder()) {
              Button()
                .backgroundColor('#ef4444')
                .paddingVertical(12)
                .borderRadius(6)
                .onClick(() => {
                  this.handleCancelOrder();
                }) {
                Text('取消订单')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#ffffff');
              }
            } else {
              Column()
                .backgroundColor('#cbd5e1')
                .paddingVertical(12)
                .borderRadius(6)
                .alignItems(ItemAlign.Center) {
                Text('无法取消订单')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#94a3b8');
              }
            }
            
            Column()
              .height(1)
              .backgroundColor('#e2e8f0')
              .marginVertical(12);
            
            Button()
              .backgroundColor('#f1f5f9')
              .paddingVertical(12)
              .borderRadius(6)
              .onClick(() => {
                AlertDialog.show({
                  title: '联系客服',
                  message: '正在连接客服...',
                  confirm: { value: '确定' }
                });
              }) {
              Text('联系客服')
                .fontSize(16)
                .fontWeight(FontWeight.Medium)
                .fontColor('#475569');
            }
          }

          // 注意事项卡片
          Column()
            .backgroundColor('#ffffff')
            .marginLeft(16)
            .marginRight(16)
            .marginBottom(80)
            .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('• 只有待发货订单可以修改收货地址')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22)
              .marginBottom(8);
            
            Text('• 只有待付款或待发货订单可以取消')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22)
              .marginBottom(8);
            
            Text('• 修改地址后可能会影响配送时效')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22)
              .marginBottom(8);
            
            Text('• 如需修改订单其他信息,请联系客服')
              .fontSize(14)
              .fontColor('#64748b')
              .lineHeight(22);
          }
        }
      }

      // 底部导航
      Row()
        .justifyContent(FlexAlign.SpaceAround)
        .backgroundColor('#ffffff')
        .borderTop({ width: 1, color: '#e2e8f0' })
        .paddingVertical(12)
        .position(Position.Fixed)
        .bottom(0)
        .width('100%') {
      
      Column()
        .alignItems(ItemAlign.Center)
        .flexGrow(1) {
        Text('🏠')
          .fontSize(20)
          .fontColor('#94a3b8')
          .marginBottom(4);
        Text('首页')
          .fontSize(12)
          .fontColor('#94a3b8');
      }
      
      Column()
        .alignItems(ItemAlign.Center)
        .flexGrow(1) {
        Text('🔍')
          .fontSize(20)
          .fontColor('#94a3b8')
          .marginBottom(4);
        Text('分类')
          .fontSize(12)
          .fontColor('#94a3b8');
      }
      
      Column()
        .alignItems(ItemAlign.Center)
        .flexGrow(1) {
        Text('🛒')
          .fontSize(20)
          .fontColor('#94a3b8')
          .marginBottom(4);
        Text('购物车')
          .fontSize(12)
          .fontColor('#94a3b8');
      }
      
      Column()
        .alignItems(ItemAlign.Center)
        .flexGrow(1)
        .paddingTop(4)
        .borderTop({ width: 2, color: '#3b82f6' }) {
        Text('📦')
          .fontSize(20)
          .fontColor('#3b82f6')
          .marginBottom(4);
        Text('订单')
          .fontSize(12)
          .fontColor('#3b82f6')
          .fontWeight(FontWeight.Medium);
      }
    }
  }
}
  1. 订单修改的核心是状态驱动的权限控制:通过强类型定义订单状态,结合权限判断函数,实现不同状态下的操作权限精准控制;
  2. 编辑/展示态切换是核心交互模式:通过单一状态变量控制地址模块的渲染形态,保证交互的流畅性和数据一致性;
  3. 风险操作需强化用户确认机制:订单取消、地址修改等重要操作需添加二次确认和明确的风险提示,降低误操作概率;
  4. 跨端适配的关键是逻辑复用+语法适配:90%以上的业务逻辑可跨端复用,仅需适配平台特有 API 和组件语法;
  5. 表单体验优化提升用户操作效率:统一的输入框样式、合理的校验规则、清晰的操作反馈,是提升表单填写体验的核心;
  6. 视觉语义化增强用户认知:通过色彩区分不同操作类型(警示/主要/次要/禁用),提升用户对操作性质的快速认知。

这份订单修改页面的跨端适配实践,验证了 React Native 与鸿蒙 ArkTS 在电商核心操作场景下的高度兼容性,为跨端电商应用的订单管理模块开发提供了可落地的技术参考。


真实演示案例代码:





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

// Base64 图标库
const ICONS_BASE64 = {
  edit: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  cancel: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  location: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  check: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  clock: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  phone: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  home: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  user: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};

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

// 订单状态类型
type OrderStatus = 'pending-payment' | 'pending-delivery' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';

// 订单项目类型
type OrderItem = {
  id: string;
  name: string;
  price: number;
  quantity: number;
  image: string;
};

// 订单类型
type Order = {
  id: string;
  orderNumber: string;
  date: string;
  status: OrderStatus;
  totalAmount: number;
  items: OrderItem[];
  shippingAddress: {
    name: string;
    phone: string;
    address: string;
  };
  paymentMethod: string;
};

// 订单修改与取消应用组件
const OrderModifyApp: React.FC = () => {
  const [order] = useState<Order>({
    id: 'o1',
    orderNumber: 'ORD202310150001',
    date: '2023-10-15',
    status: 'pending-delivery',
    totalAmount: 10997,
    items: [
      { id: 'i1', name: 'iPhone 15 Pro Max', price: 9999, quantity: 1, image: 'https://via.placeholder.com/60x60' },
      { id: 'i2', name: '手机壳', price: 299, quantity: 1, image: 'https://via.placeholder.com/60x60' },
      { id: 'i3', name: '钢化膜', price: 699, quantity: 1, image: 'https://via.placeholder.com/60x60' }
    ],
    shippingAddress: {
      name: '张三',
      phone: '138****8888',
      address: '北京市朝阳区某某街道123号'
    },
    paymentMethod: '支付宝'
  });

  const [newAddress, setNewAddress] = useState({
    name: order.shippingAddress.name,
    phone: order.shippingAddress.phone,
    address: order.shippingAddress.address
  });

  const [editingField, setEditingField] = useState<string | null>(null);

  const canModifyAddress = (): boolean => {
    return order.status === 'pending-payment' || order.status === 'pending-delivery';
  };

  const canCancelOrder = (): boolean => {
    return order.status === 'pending-payment' || order.status === 'pending-delivery';
  };

  const handleSaveAddress = () => {
    if (!newAddress.name || !newAddress.phone || !newAddress.address) {
      Alert.alert('提示', '请填写完整的收货信息');
      return;
    }

    Alert.alert(
      '确认修改',
      '您确定要修改收货地址吗?',
      [
        {
          text: '取消',
          style: 'cancel'
        },
        {
          text: '确定',
          onPress: () => {
            Alert.alert('成功', '收货地址已修改成功');
            setEditingField(null);
          }
        }
      ]
    );
  };

  const handleCancelOrder = () => {
    Alert.alert(
      '取消订单',
      '您确定要取消此订单吗?取消后订单将无法恢复。',
      [
        {
          text: '取消',
          style: 'cancel'
        },
        {
          text: '确定',
          onPress: () => {
            Alert.alert('成功', '订单已取消');
          }
        }
      ]
    );
  };

  const getStatusText = (status: OrderStatus): string => {
    switch (status) {
      case 'pending-payment': return '待付款';
      case 'pending-delivery': return '待发货';
      case 'shipped': return '已发货';
      case 'delivered': return '已签收';
      case 'cancelled': return '已取消';
      case 'refunded': return '已退款';
      default: return '未知状态';
    }
  };

  const getStatusColor = (status: OrderStatus): string => {
    switch (status) {
      case 'pending-payment': return '#f59e0b';
      case 'pending-delivery': return '#3b82f6';
      case 'shipped': return '#10b981';
      case 'delivered': return '#10b981';
      case 'cancelled': return '#9ca3af';
      case 'refunded': return '#8b5cf6';
      default: return '#9ca3af';
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <Text style={styles.title}>订单修改</Text>
        <Text style={styles.orderNumber}>订单号: {order.orderNumber}</Text>
      </View>

      <ScrollView style={styles.content}>
        {/* 订单状态卡片 */}
        <View style={styles.statusCard}>
          <View style={styles.statusHeader}>
            <Text style={[styles.statusText, { color: getStatusColor(order.status) }]}>
              {getStatusText(order.status)}
            </Text>
          </View>
          <Text style={styles.statusDescription}>
            {order.status === 'pending-delivery' 
              ? '订单尚未发货,您可以修改收货地址或取消订单' 
              : order.status === 'pending-payment'
              ? '订单尚未付款,您可以修改收货地址或取消订单'
              : '订单已发货,无法修改收货地址'}
          </Text>
        </View>

        {/* 修改收货地址 */}
        <View style={styles.addressCard}>
          <Text style={styles.cardTitle}>收货地址</Text>
          
          {editingField === 'address' ? (
            <View style={styles.editForm}>
              <View style={styles.inputGroup}>
                <Text style={styles.label}>收货人姓名</Text>
                <TextInput
                  style={styles.input}
                  value={newAddress.name}
                  onChangeText={(text) => setNewAddress({...newAddress, name: text})}
                  placeholder="请输入收货人姓名"
                />
              </View>
              
              <View style={styles.inputGroup}>
                <Text style={styles.label}>联系电话</Text>
                <TextInput
                  style={styles.input}
                  value={newAddress.phone}
                  onChangeText={(text) => setNewAddress({...newAddress, phone: text})}
                  placeholder="请输入联系电话"
                  keyboardType="phone-pad"
                />
              </View>
              
              <View style={styles.inputGroup}>
                <Text style={styles.label}>详细地址</Text>
                <TextInput
                  style={[styles.input, styles.textArea]}
                  value={newAddress.address}
                  onChangeText={(text) => setNewAddress({...newAddress, address: text})}
                  placeholder="请输入详细地址"
                  multiline
                />
              </View>
              
              <View style={styles.buttonGroup}>
                <TouchableOpacity 
                  style={styles.cancelButton}
                  onPress={() => setEditingField(null)}
                >
                  <Text style={styles.cancelButtonText}>取消</Text>
                </TouchableOpacity>
                <TouchableOpacity 
                  style={styles.saveButton}
                  onPress={handleSaveAddress}
                >
                  <Text style={styles.saveButtonText}>保存</Text>
                </TouchableOpacity>
              </View>
            </View>
          ) : (
            <View style={styles.addressInfo}>
              <View style={styles.contactInfo}>
                <Text style={styles.contactName}>{newAddress.name}</Text>
                <Text style={styles.contactPhone}>{newAddress.phone}</Text>
              </View>
              <Text style={styles.fullAddress}>{newAddress.address}</Text>
              
              {canModifyAddress() && (
                <TouchableOpacity 
                  style={styles.editButton}
                  onPress={() => setEditingField('address')}
                >
                  <Text style={styles.editButtonText}>修改地址</Text>
                </TouchableOpacity>
              )}
            </View>
          )}
        </View>

        {/* 订单商品 */}
        <View style={styles.orderItemsCard}>
          <Text style={styles.orderItemsTitle}>订单商品</Text>
          {order.items.map(item => (
            <View key={item.id} style={styles.itemRow}>
              <View style={styles.itemInfo}>
                <Text style={styles.itemName}>{item.name}</Text>
                <Text style={styles.itemPrice}>¥{item.price} x {item.quantity}</Text>
              </View>
            </View>
          ))}
          <View style={styles.orderSummary}>
            <Text style={styles.totalText}>商品总数: {order.items.reduce((sum, item) => sum + item.quantity, 0)}</Text>
            <Text style={styles.totalAmount}>订单总额: ¥{order.totalAmount}</Text>
          </View>
        </View>

        {/* 订单信息 */}
        <View style={styles.orderInfoCard}>
          <Text style={styles.orderInfoTitle}>订单信息</Text>
          <View style={styles.infoRow}>
            <Text style={styles.infoLabel}>下单时间:</Text>
            <Text style={styles.infoValue}>{order.date}</Text>
          </View>
          <View style={styles.infoRow}>
            <Text style={styles.infoLabel}>支付方式:</Text>
            <Text style={styles.infoValue}>{order.paymentMethod}</Text>
          </View>
        </View>

        {/* 操作选项 */}
        <View style={styles.actionsCard}>
          <Text style={styles.actionsTitle}>订单操作</Text>
          
          {canCancelOrder() ? (
            <TouchableOpacity 
              style={styles.cancelOrderButton}
              onPress={handleCancelOrder}
            >
              <Text style={styles.cancelOrderButtonText}>取消订单</Text>
            </TouchableOpacity>
          ) : (
            <View style={styles.disabledButton}>
              <Text style={styles.disabledButtonText}>无法取消订单</Text>
            </View>
          )}
          
          <View style={styles.separator} />
          
          <TouchableOpacity 
            style={styles.contactSupportButton}
            onPress={() => Alert.alert('联系客服', '正在连接客服...')}
          >
            <Text style={styles.contactSupportButtonText}>联系客服</Text>
          </TouchableOpacity>
        </View>

        {/* 注意事项 */}
        <View style={styles.notesCard}>
          <Text style={styles.notesTitle}>注意事项</Text>
          <Text style={styles.noteItem}>• 只有待发货订单可以修改收货地址</Text>
          <Text style={styles.noteItem}>• 只有待付款或待发货订单可以取消</Text>
          <Text style={styles.noteItem}>• 修改地址后可能会影响配送时效</Text>
          <Text style={styles.noteItem}>• 如需修改订单其他信息,请联系客服</Text>
        </View>
      </ScrollView>

      {/* 底部导航 */}
      <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: 'column',
    padding: 16,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  orderNumber: {
    fontSize: 14,
    color: '#64748b',
  },
  content: {
    flex: 1,
    marginTop: 12,
  },
  statusCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 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,
  },
  statusText: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  statusDescription: {
    fontSize: 14,
    color: '#64748b',
  },
  addressCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  cardTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  editForm: {
    // 编辑表单位置
  },
  inputGroup: {
    marginBottom: 16,
  },
  label: {
    fontSize: 14,
    color: '#64748b',
    marginBottom: 4,
  },
  input: {
    borderWidth: 1,
    borderColor: '#e2e8f0',
    borderRadius: 6,
    padding: 12,
    fontSize: 16,
    backgroundColor: '#f8fafc',
  },
  textArea: {
    height: 80,
    textAlignVertical: 'top',
  },
  buttonGroup: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginTop: 16,
  },
  cancelButton: {
    flex: 0.48,
    backgroundColor: '#f1f5f9',
    paddingVertical: 12,
    borderRadius: 6,
    alignItems: 'center',
  },
  cancelButtonText: {
    color: '#475569',
    fontSize: 16,
    fontWeight: '500',
  },
  saveButton: {
    flex: 0.48,
    backgroundColor: '#3b82f6',
    paddingVertical: 12,
    borderRadius: 6,
    alignItems: 'center',
  },
  saveButtonText: {
    color: '#ffffff',
    fontSize: 16,
    fontWeight: '500',
  },
  addressInfo: {
    padding: 12,
    backgroundColor: '#f8fafc',
    borderRadius: 8,
  },
  contactInfo: {
    flexDirection: 'row',
    marginBottom: 4,
  },
  contactName: {
    fontSize: 14,
    fontWeight: '500',
    color: '#1e293b',
    marginRight: 12,
  },
  contactPhone: {
    fontSize: 14,
    color: '#64748b',
  },
  fullAddress: {
    fontSize: 14,
    color: '#64748b',
  },
  editButton: {
    marginTop: 12,
    backgroundColor: '#f1f5f9',
    paddingVertical: 8,
    borderRadius: 6,
    alignItems: 'center',
  },
  editButtonText: {
    color: '#475569',
    fontSize: 14,
    fontWeight: '500',
  },
  orderItemsCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  orderItemsTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  itemRow: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 12,
  },
  itemInfo: {
    flex: 1,
  },
  itemName: {
    fontSize: 14,
    color: '#1e293b',
    marginBottom: 4,
  },
  itemPrice: {
    fontSize: 12,
    color: '#64748b',
  },
  orderSummary: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginTop: 12,
    paddingTop: 12,
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
  },
  totalText: {
    fontSize: 14,
    color: '#64748b',
  },
  totalAmount: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#ef4444',
  },
  orderInfoCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  orderInfoTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  infoRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginBottom: 8,
  },
  infoLabel: {
    fontSize: 14,
    color: '#64748b',
    flex: 0.4,
  },
  infoValue: {
    fontSize: 14,
    color: '#1e293b',
    flex: 0.6,
    textAlign: 'right',
  },
  actionsCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 12,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  actionsTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  cancelOrderButton: {
    backgroundColor: '#ef4444',
    paddingVertical: 12,
    borderRadius: 6,
    alignItems: 'center',
  },
  cancelOrderButtonText: {
    color: '#ffffff',
    fontSize: 16,
    fontWeight: '500',
  },
  disabledButton: {
    backgroundColor: '#cbd5e1',
    paddingVertical: 12,
    borderRadius: 6,
    alignItems: 'center',
  },
  disabledButtonText: {
    color: '#94a3b8',
    fontSize: 16,
    fontWeight: '500',
  },
  separator: {
    height: 1,
    backgroundColor: '#e2e8f0',
    marginVertical: 12,
  },
  contactSupportButton: {
    backgroundColor: '#f1f5f9',
    paddingVertical: 12,
    borderRadius: 6,
    alignItems: 'center',
  },
  contactSupportButtonText: {
    color: '#475569',
    fontSize: 16,
    fontWeight: '500',
  },
  notesCard: {
    backgroundColor: '#ffffff',
    marginHorizontal: 16,
    marginBottom: 80,
    borderRadius: 12,
    padding: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  notesTitle: {
    fontSize: 16,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 12,
  },
  noteItem: {
    fontSize: 14,
    color: '#64748b',
    lineHeight: 22,
    marginBottom: 8,
  },
  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 OrderModifyApp;


请添加图片描述


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述
本文探讨了一个基于React Native实现的电商订单修改系统,重点分析了其架构设计、技术实现和跨端适配策略。系统采用TypeScript构建了类型安全的订单数据模型,通过React Hooks进行状态管理,实现了地址修改、订单取消等核心功能,并设计了精细的权限控制逻辑。在跨端适配方面,系统采用Base64图标处理、Dimensions API等技术确保在鸿蒙系统上的兼容性。该实现不仅功能完善,还具有良好的可维护性和扩展性,为电商应用的订单管理模块开发提供了可落地的技术参考。

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

Logo

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

更多推荐