合并受阻
感谢提交 Pull Requests!
Thanks for submitting a pull request.


【AI-Review】【严重】【基础代码问题】【代码逻辑错误】getProducts/getSubscriptions 参数 skus 嵌套数组导致查询失败
● 问题:在 getItemsByType 方法中,productIds 已经是 string[] 类型(由 this.state.skuIds.split(',').map(s => s.trim()).filter(Boolean) 生成),但构造 params 时使用了 const params = { skus: [productIds] },多包了一层数组。这会导致 params.skus 变成 string[][] 嵌套数组(例如 [['sku_001', 'sku_002']]),而不是 react-native-iap API 期望的 string[](即 ['sku_001', 'sku_002'])。
根据 react-native-iap 的 API 定义(src/iap.ts),getProducts 的签名为 ({ skus: string[] }): Promise<Array<Product>>,且入口校验 if (!skus?.length) 会通过(因为 [['sku_001', 'sku_002']].length === 1),但实际传递给鸿蒙原生模块 Iap.getProducts({skus}) 的是嵌套数组,原生模块无法正确解析 SKU 列表。
● 影响:严重。当用户点击"按类型获取商品"按钮时(默认 skuIds 为 'sku_001,sku_002'),由于 params.skus 是 [['sku_001', 'sku_002']] 而非 ['sku_001', 'sku_002'],原生模块接收到的不是字符串数组而是嵌套数组,导致商品查询失败或返回空结果,测试用例的核心功能无法正常运行。
同一 PR 的 test.tsx 中 getSubscriptions({ skus: ['SubProduct01001'] }) 和 getProducts({ skus: ['ohos_consume_002'] }) 的正确用法证明了 API 期望 skus 为 string[] 而非 string[][]。
● 建议:移除多余的数组包装,直接使用 productIds:
const params = { skus: productIds };


【AI-Review】【一般】【基础代码问题】【稳定性问题】_crop 方法未捕获 ImageEditor.cropImage 异常
● 问题:ImageCropperFull 组件的 _crop 方法是 async 函数,调用了 await ImageEditor.cropImage(this.state.photoUri, imageCropData),但没有使用 try-catch 包裹。如果 ImageEditor.cropImage 抛出异常(例如用户输入非数字导致 parseFloat 返回 NaN、选择 'local' 类型但 filePath 为 null、原生模块处理失败等),异常会成为未处理的 Promise 拒绝。
对比同 PR 的 SquareImageCropper.tsx 第 158-175 行的 _crop 方法,该方法使用了 try-catch 捕获 cropError 并通过 this.setState({ cropError }) 更新状态,UI 通过 {cropError?.message} 显示错误信息。但 ImageCropperFull.tsx 的 _crop 方法没有同样的错误处理。
触发路径:用户在 ImageCropperFull 界面输入无效的裁剪参数(如 offset/size 留空导致 parseFloat('') 返回 NaN)→ 边界检查 imageCropData.size.width + imageCropData.offset.x > this.state.photoWidth 中 NaN > number 结果为 false,不会拦截 → 进入 ImageEditor.cropImage 调用 → 原生模块收到 NaN 参数抛出异常 → async 函数无 try-catch → 未处理的 Promise 拒绝。
● 影响:一般。当 ImageEditor.cropImage 失败时,由于没有 try-catch,用户看不到任何错误提示,且可能触发 React Native 的未处理 Promise 拒绝警告,影响调试和用户体验。
● 建议:使用 try-catch 包裹 ImageEditor.cropImage 调用,并在 catch 中通过 Alert 提示用户:
try {
const cropResult = await ImageEditor.cropImage(this.state.photoUri, imageCropData);
// ... 后续处理
} catch (e) {
Alert.alert('裁剪失败', String(e));
}


【AI-Review】【一般】【基础代码问题】【代码逻辑错误】acknowledgePurchase 循环中调用 Alert.alert 导致多次提示被覆盖
● 问题:acknowledgePurchase 方法在 for 循环中对 this.state.availablePurchases 的每个订单调用 await finishTransaction(...),然后在循环体内直接调用 Alert.alert('确认成功', ...) 或 Alert.alert('确认失败', ...)。当存在多条未完成订单时,循环会连续多次调用 Alert.alert,而 Alert.alert 是异步的模态对话框,后调用的会覆盖前面的,用户最终只能看到最后一个订单的结果提示。
触发路径:用户点击"确认完成所有订单"按钮 → fetchAvailablePurchases 已查询到 N 条订单 → 进入 for 循环 → 对每条订单调用 finishTransaction 并 Alert.alert → N 次 Alert 调用互相覆盖 → 用户只看到最后一条订单的结果。
● 影响:一般。当有多条未完成订单且部分成功、部分失败时,用户无法从 UI 上得知每条订单的处理结果,只看到最后一个订单的提示,影响测试用例对 finishTransaction 行为的验证。
● 建议:将循环中的 Alert.alert 移到循环外,汇总结果后统一提示。例如统计成功/失败数量后弹出一次 Alert:
let successCount = 0;
let failCount = 0;
for (let i = 0; i < this.state.availablePurchases.length; i++) {
const purchase = this.state.availablePurchases[i];
const isConsumable = purchase.productTypeIos === 'inapp';
try {
const result = await finishTransaction({ purchase, isConsumable });
if (result) { successCount++; } else { failCount++; }
} catch (e) {
failCount++;
}
}
Alert.alert('确认结果', `成功 ${successCount} 条,失败 ${failCount} 条`);


test: 添加0.61 iap 和 image-editor 测试Demo