13404089107
2026-04-29 79a1de9cff6a5b6185bc9083f8697d69a98cdc52
feat: 在APP端优先使用原生拨号功能拨打客服电话

- 修改多个页面的客服电话拨打逻辑,APP端优先尝试使用原生能力(`plus.runtime.openURL` 或 `plus.device.dial`)打开系统拨号页
- 更新相关函数注释以明确新的行为
- 在直播观看页,将客服咨询改为直接获取并拨打客服电话,而非跳转页面
- 移除调试代码并注释掉推送模块中设置角标的测试代码
5个文件已修改
154 ■■■■■ 已修改文件
traditionalApp/App.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/courseDetail/courseDetail.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/helpCenter/helpCenter.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/myCourseDetail/myCourseDetail.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/watchLive/watchLive.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/App.vue
@@ -30,8 +30,9 @@
        });
        jpushModule.addNotificationListener(result => {
            plus.runtime.setBadgeNumber('111111');
            jpushModule.setBadge('2222222222222')
            console.log('qeqwewqe', result);
            // plus.runtime.setBadgeNumber('111111');
            // jpushModule.setBadge('2222222222222')
        });
traditionalApp/pages/courseDetail/courseDetail.vue
@@ -844,7 +844,7 @@
    }
    /**
     * 拨打后台系统配置中的客服电话,未配置时给出兜底提示。
     * 拨打后台系统配置中的客服电话,APP 端优先走原生拨号页。
     */
    function handleConsult() {
        if (isReadonlyDisplayMode) {
@@ -858,12 +858,35 @@
            })
            return
        }
        if (openNativeDialer(servicePhone)) {
            return
        }
        uni.makePhoneCall({
            phoneNumber: servicePhone,
        })
    }
    /**
     * APP 端优先使用原生能力打开系统拨号页。
     */
    function openNativeDialer(phoneNumber : string) {
        // #ifdef APP-PLUS
        try {
            plus.runtime.openURL(`tel:${phoneNumber}`)
            return true
        } catch (error) {
            try {
                plus.device.dial(phoneNumber, false)
                return true
            } catch (dialError) {
                return false
            }
        }
        // #endif
        return false
    }
    /**
     * 拉起或跳转下载 APP
     */
    function openApp() {
traditionalApp/pages/helpCenter/helpCenter.vue
@@ -153,7 +153,7 @@
}
/**
 * 拨打系统设置中的客服电话,未配置时给出兜底提示。
 * 拨打系统设置中的客服电话,APP 端优先走原生拨号页。
 */
function handleContact() {
    const servicePhone = normalizePhoneNumber(helpCenterData.value.servicePhone)
@@ -162,6 +162,9 @@
            title: '暂未配置客服电话',
            icon: 'none',
        })
        return
    }
    if (openNativeDialer(servicePhone)) {
        return
    }
    uni.makePhoneCall({
@@ -176,6 +179,26 @@
}
/**
 * APP 端优先使用原生能力打开系统拨号页。
 */
function openNativeDialer(phoneNumber: string) {
    // #ifdef APP-PLUS
    try {
        plus.runtime.openURL(`tel:${phoneNumber}`)
        return true
    } catch (error) {
        try {
            plus.device.dial(phoneNumber, false)
            return true
        } catch (dialError) {
            return false
        }
    }
    // #endif
    return false
}
/**
 * 跳转到常见问题详情页。
 */
function goFaqDetail(item: HelpCenterQuestionItem) {
traditionalApp/pages/myCourseDetail/myCourseDetail.vue
@@ -755,7 +755,7 @@
}
/**
 * 拨打系统配置的客服电话,未配置时给出提示。
 * 拨打系统配置的客服电话,APP 端优先走原生拨号页。
 */
function handleConsult() {
    const servicePhone = detail.value.servicePhone.trim()
@@ -766,12 +766,35 @@
        })
        return
    }
    if (openNativeDialer(servicePhone)) {
        return
    }
    uni.makePhoneCall({
        phoneNumber: servicePhone,
    })
}
/**
 * APP 端优先使用原生能力打开系统拨号页。
 */
function openNativeDialer(phoneNumber: string) {
    // #ifdef APP-PLUS
    try {
        plus.runtime.openURL(`tel:${phoneNumber}`)
        return true
    } catch (error) {
        try {
            plus.device.dial(phoneNumber, false)
            return true
        } catch (dialError) {
            return false
        }
    }
    // #endif
    return false
}
/**
 * 底部下载按钮直接下载当前正在播放的章节。
 */
function handleCurrentVideoDownload() {
traditionalApp/pages/watchLive/watchLive.vue
@@ -160,6 +160,7 @@
    import { computed, getCurrentInstance, nextTick, ref } from 'vue';
    import { onHide, onLoad, onShow, onUnload } from '@dcloudio/uni-app';
    import { getLiveCourseDetail, getLiveQuizStatus, submitLiveQuiz, uploadLiveWatchRecord } from './service';
    import { getHelpCenter } from '../helpCenter/service';
    import config from '@/config/index.js';
    type LiveActionStatus = 'RESERVABLE' | 'RESERVED' | 'WATCHABLE' | 'CLOSED'
@@ -336,18 +337,83 @@
    }
    /**
     * 跳转到客服咨询页面。
     * 获取帮助中心客服电话并直接拉起系统拨号。
     */
    function goCustomerService() {
    async function goCustomerService() {
        if (isReadonlyDisplayMode) {
            return
        }
        uni.navigateTo({
            url: '/pages/customerService/customerService',
        const servicePhone = await fetchServicePhone()
        if (!servicePhone) {
            uni.showToast({
                title: '暂未配置客服电话',
                icon: 'none',
            })
            return
        }
        if (openNativeDialer(servicePhone)) {
            return
        }
        uni.makePhoneCall({
            phoneNumber: servicePhone,
            fail() {
                uni.showToast({
                    title: '拨号失败,请检查客服电话配置',
                    icon: 'none',
                })
            },
        })
    }
    /**
     * 从帮助中心接口读取客服电话。
     */
    async function fetchServicePhone() {
        try {
            const response = await getHelpCenter()
            if (response?.code !== 0 || !response.data) {
                return ''
            }
            return normalizePhoneNumber((response.data as Record<string, unknown>).servicePhone)
        } catch (error) {
            return ''
        }
    }
    /**
     * APP 端优先使用原生能力打开系统拨号页。
     */
    function openNativeDialer(phoneNumber: string) {
        // #ifdef APP-PLUS
        try {
            plus.runtime.openURL(`tel:${phoneNumber}`)
            return true
        } catch (error) {
            try {
                plus.device.dial(phoneNumber, false)
                return true
            } catch (dialError) {
                return false
            }
        }
        // #endif
        return false
    }
    /**
     * 清洗客服电话,兼容空格、横杠和中文括号等展示字符。
     */
    function normalizePhoneNumber(value: unknown) {
        if (typeof value !== 'string') {
            return ''
        }
        return value
            .trim()
            .replace(/[()()\s-]/g, '')
            .replace(/(?!^)\+/g, '')
    }
    /**
     * 将后台题目列表转换成前端答题面板使用的数据结构。
     */
    function createQuizQuestions(quizQuestions ?: QuizQuestionResponse[]) : QuizQuestionItem[] {