H5 必须用 tel: 协议 a 标签,App 需 manifest 权限+运行时授权,微信小程序需条件编译+wx.makePhoneCall+权限字段 phoneNumber;所有平台均需号码清洗为纯数字或带+国际号。

不能只写一个 uni.makePhoneCall 就上线——H5 环境下它完全静默失败,不报错、不弹窗、用户点了没反应,这是最常翻车的第一步。
为什么 H5 上点击按钮没反应?
H5 浏览器无法调用原生拨号能力,uni.makePhoneCall 在该平台直接被忽略,success/fail 回调都不会触发。唯一可靠方式是用 HTML 原生的 tel: 协议链接。
- 必须用
<a>标签包裹,<button @click>或<view @click>在 H5 下无效 - 号码必须纯数字:
"400-123-4567"→ 清洗为"4001234567",否则部分 Android 机型识别失败 - 加
rel="noopener"和target="_self"防止跳转异常(尤其在某些 WebView 中) - 示例:
<a :href="'tel:' + cleanPhone(phoneNumber)" rel="noopener" target="_self">拨打客服</a>
App 端拨号失败的常见原因
Android 11+(API 30)起,系统会拦截未声明权限的拨号行为,即使代码写了也静默失败;iOS 则必须真机测试,模拟器不支持。
- manifest.json 中必须勾选「拨打电话」权限(Android 设置 → 权限配置)
- 运行时检查平台:
uni.getSystemInfoSync().platform === 'android' - 调用前建议授权:
uni.authorize({scope: 'scope.callPhone'})(iOS 仅占位,H5 无效) - 若拒绝,必须跳转设置页:
uni.openSetting(),否则后续点击永远无响应 - 号码清洗不可少:
phoneNumber.replace(/[^0-9+]/g, ''),保留+用于国际号(如+8613800138000)
微信小程序怎么写才不报错?
微信小程序不认 uni.makePhoneCall,必须用 wx.makePhoneCall,且需条件编译 + 权限字段名特殊(不是 callPhone,而是 phoneNumber)。
- 基础写法:
<button open-type="tel" :data-tel="phoneNumber">拨打{{phoneNumber}}</button>(无需 JS,微信原生支持) - 若用 JS 调用,需
#ifdef MP-WEIXIN包裹,并调用wx.makePhoneCall({ phoneNumber }) - 前置检查权限:
uni.getSetting查authSetting['scope.phoneNumber'],注意字段名拼写 - 首次拒绝后微信不再弹框,必须引导用户手动开启(比如弹
uni.showModal提示去「设置 > 权限管理」)
图片点击拨号为什么经常失效?
<image> 元素默认不触发 @click,尤其在安卓 WebView 或旧版 HBuilderX 下,事件常被父容器拦截或忽略。
- 优先用容器包裹:
<view @click="callPhone"><image src="" /></view> - 若必须绑在
<image>上,加样式:style="cursor: pointer; pointer-events: auto;" - 确保图片路径正确,加载失败会导致整个区域无响应
- iOS 对
pointer-events更敏感,显式声明更稳妥
真正麻烦的从来不是“怎么写”,而是“在哪写”——平台判断漏掉 H5、号码清洗放在调用后、权限检查只做一次就不管后续拒绝,这些细节才是线上用户打不通电话的根源。


















