fix: 修复鸿蒙元服务商品详情页空白及接口兼容问题

1. 移除view组件无效的scroll-y属性,避免鸿蒙JSVM静默不渲染导致页面空白
2. 删除冗余的商品分类页面路由配置
3. 为ref调用和接口请求添加try-catch与空值防御,避免极端场景下崩溃
4. 补充鸿蒙元服务接口调用的兼容性处理,确保请求正常发起
5. 调整loading隐藏时机和异常捕获逻辑,优化页面容错能力
This commit is contained in:
2026-07-20 08:44:15 +08:00
parent cd2705e5b9
commit 73776841d8
4 changed files with 73 additions and 105 deletions

View File

@@ -1,6 +1,8 @@
<template>
<view>
<view scroll-y="true" class="goods-detail" :class="isIphoneX ? 'active' : ''">
<!-- 修复鸿蒙元服务: 移除无效的 scroll-y="true" 属性 (scroll-y 是 <scroll-view> 的指令属性)
鸿蒙 JSVM 早期版本遇到无效 attribute 会让 view 子树静默不渲染, 导致整个详情页空白 -->
<view class="goods-detail" :class="isIphoneX ? 'active' : ''">
<view class="goods-container">
<!-- AI客服悬浮按钮 -->
<view class="ai-chat-float-btn" @tap.stop="$emit('aiChatClick')" v-if="showAIChatBtn">

View File

@@ -102,11 +102,14 @@ export default {
try {
await this.getGoodsSkuDetail();
} catch (e) {
console.error('getGoodsSkuDetail failed on 鸿蒙:', e);
console.error('getGoodsSkuDetail failed:', e);
// 即使失败也要保证 loading-cover 关闭, 避免空白屏
if (this.$refs.loadingCover && typeof this.$refs.loadingCover.hide === 'function') {
this.$refs.loadingCover.hide();
}
setTimeout(() => {
try {
const ref = this.$refs && this.$refs.loadingCover;
if (ref && typeof ref.hide === 'function') ref.hide();
} catch (e2) { /* swallow */ }
}, 0);
}
},
onHide() {
@@ -129,14 +132,28 @@ export default {
},
// 获取商品详情
async getGoodsSkuDetail() {
let res = await this.$api.sendRequest({
url: '/api/goodssku/detail',
async: false,
data: {
sku_id: this.skuId,
goods_id: this.goodsId,
let res;
try {
// 修复鸿蒙元服务: 必须传 async: false !
// 当 App.vue 的 boot (lang/theme/remote-config) 未完成时,
// sendRequest 在 async !== false 模式下会直接 return undefined (不返回 promise),
// 导致 res.code undefined / res.data 抛 TypeError, 整个 onShow 失败.
res = await this.$api.sendRequest({
url: '/api/goodssku/detail',
async: false,
data: {
sku_id: this.skuId,
goods_id: this.goodsId,
}
});
// 防御: 即便 async:false 仍可能在极端情况下返回 undefined
if (!res || typeof res !== 'object') {
throw new Error('sendRequest returned non-object response (likely boot not complete)');
}
});
} catch (e) {
console.error('getGoodsSkuDetail sendRequest failed:', e);
throw e;
}
let data = res.data;
if (data.goods_sku_detail != null) {
if (data.goods_sku_detail.promotion_type == 'presale' && data.goods_sku_detail.presale_id) {
@@ -176,19 +193,24 @@ export default {
goods_id: this.goodsId
};
// 让首屏主区域先绘制: 把非首屏必要的字段变换 (sku_images split, JSON.parse, 属性去重等)
// 放到下一个 tick, 微信小程序下首帧明显更快, 用户感知"加载完成"提前约 100-200ms。
// 兼容鸿蒙元服务: $nextTick / Promise 在某些 JSVM 实现下不可靠, 用 setTimeout 兜底
// 让首屏主区域先绘制
// 兼容鸿蒙元服务: $nextTick 在某些 JSVM 实现下不可靠, 用 setTimeout 兜底
// #ifdef MP-HARMONY
await new Promise(resolve => setTimeout(resolve, 16));
// #endif
// #endif
// #ifndef MP-HARMONY
await this.$nextTick();
// #endif
// 关闭 loading-cover 提前到 nextTick 后, 让用户看到首屏内容
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
// 用 setTimeout 0 推迟到下一个 task, 避开当前 sync 阶段 vendor 报错导致 hide 失败
setTimeout(() => {
try {
const ref = this.$refs && this.$refs.loadingCover;
if (ref && typeof ref.hide === 'function') ref.hide();
} catch (e) { /* swallow */ }
}, 0);
// 处理商品数据 (同步字段变换 + 后台并发 getGoodsForm)
await this.handleGoodsSkuData();