From 9312eceb94a581b82d681666036ab6883e2a9b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=9D=E5=BF=83?= <13773726377@163.com> Date: Thu, 2 Apr 2026 11:37:09 +0800 Subject: [PATCH] 1 --- src/components/ContactSelectModal.vue | 284 ++++++++++++++++++++++--- src/components/petOrder/call-modal.vue | 222 +++++++++++++++++-- 2 files changed, 457 insertions(+), 49 deletions(-) diff --git a/src/components/ContactSelectModal.vue b/src/components/ContactSelectModal.vue index db3a6e8..440101c 100644 --- a/src/components/ContactSelectModal.vue +++ b/src/components/ContactSelectModal.vue @@ -7,7 +7,7 @@ - + + + + @@ -80,19 +102,37 @@ export default { } }, emits: ['close', 'phoneCall', 'imSuccess', 'imError', 'onlineConsult'], + data() { + return { + showPrivacyModal: false, // 隐私协议弹窗显示状态 + pendingPhoneNumber: null // 暂存的待拨打的号码 + } + }, + watch: { + // 监听弹窗关闭,重置隐私弹窗状态 + visible(newVal) { + if (!newVal) { + this.showPrivacyModal = false + this.pendingPhoneNumber = null + } + } + }, methods: { handleClose() { this.$emit('close') }, + handleOnlineConsult() { this.$emit('onlineConsult') this.$emit('close') }, + imCallback(e) { console.log('跳转IM客服成功', e.detail) this.$emit('imSuccess', e) this.$emit('close') }, + onimError(e) { console.log('拉起IM客服失败', e.detail) this.$emit('imError', e) @@ -101,47 +141,153 @@ export default { icon: 'none' }) }, - handlePhoneCall() { - this.$emit('phoneCall', this.servicePhone) - this.$emit('close') + + // ========== 隐私协议相关方法 ========== + + // 打开隐私协议详情 + openPrivacyContract() { + // #ifdef MP-TOUTIAO + tt.openPrivacyContract({ + fail: (err) => { + console.error('打开隐私协议失败', err) + uni.showToast({ + title: '无法打开协议', + icon: 'none' + }) + } + }) + // #endif - if (this.servicePhone) { - // 抖音小程序拨打电话 - uni.makePhoneCall({ - phoneNumber: this.servicePhone, - success: () => { - console.log('拨打电话成功') - }, - fail: (err) => { - console.error('拨打电话失败', err) - // 失败时显示客服电话供用户手动拨打 - uni.showModal({ - title: '客服电话', - content: this.servicePhone, - confirmText: '复制', - cancelText: '知道了', - success: (res) => { - if (res.confirm) { - uni.setClipboardData({ - data: this.servicePhone, - success: () => { - uni.showToast({ - title: '电话已复制', - icon: 'success' - }) - } - }) - } - } - }) + // #ifndef MP-TOUTIAO + uni.showToast({ + title: '请在设置中查看隐私协议', + icon: 'none' + }) + // #endif + }, + + // 用户同意隐私协议 + onAgreePrivacy(e) { + console.log('用户已同意隐私协议', e) + this.showPrivacyModal = false + uni.showToast({ + title: '已授权', + icon: 'success' + }) + // 同意后,执行之前暂存的拨号请求 + if (this.pendingPhoneNumber) { + this.doMakePhoneCall(this.pendingPhoneNumber) + this.pendingPhoneNumber = null + } + }, + + // 用户拒绝隐私协议 + onDisagreePrivacy() { + this.showPrivacyModal = false + this.pendingPhoneNumber = null + uni.showToast({ + title: '未授权,无法使用拨号功能', + icon: 'none' + }) + }, + + // 检查隐私授权状态(抖音专用) + checkPrivacyAuthorization(phoneNumber, callback) { + // #ifdef MP-TOUTIAO + tt.getPrivacySetting({ + success: (res) => { + console.log('隐私授权状态:', res) + if (res.needAuthorization) { + // 未授权,显示隐私弹窗,并暂存电话号码 + this.pendingPhoneNumber = phoneNumber + this.showPrivacyModal = true + callback && callback(false) + } else { + // 已授权,直接拨号 + callback && callback(true) } - }) - } else { + }, + fail: (err) => { + console.error('获取隐私设置失败', err) + // 获取失败时,直接尝试拨号(降级处理) + callback && callback(true) + } + }) + // #endif + + // #ifndef MP-TOUTIAO + // 非抖音平台,直接拨号 + callback && callback(true) + // #endif + }, + + // 实际拨号方法 + doMakePhoneCall(phoneNumber) { + if (!phoneNumber) { uni.showToast({ title: '客服电话暂未设置', icon: 'none' }) + return } + + uni.makePhoneCall({ + phoneNumber: phoneNumber, + success: () => { + console.log('拨打电话成功') + }, + fail: (err) => { + console.error('拨打电话失败', err) + // 失败时显示客服电话供用户手动拨打 + uni.showModal({ + title: '客服电话', + content: phoneNumber, + confirmText: '复制', + cancelText: '知道了', + success: (res) => { + if (res.confirm) { + uni.setClipboardData({ + data: phoneNumber, + success: () => { + uni.showToast({ + title: '电话已复制', + icon: 'success' + }) + } + }) + } + } + }) + } + }) + }, + + // ========== 修改后的拨号入口 ========== + + handlePhoneCall() { + const phoneNumber = this.servicePhone + + // 先触发父组件的 phoneCall 事件 + this.$emit('phoneCall', phoneNumber) + + if (!phoneNumber) { + uni.showToast({ + title: '客服电话暂未设置', + icon: 'none' + }) + return + } + + // 检查隐私授权状态后再拨号 + this.checkPrivacyAuthorization(phoneNumber, (authorized) => { + if (authorized) { + this.doMakePhoneCall(phoneNumber) + } + // 未授权时,checkPrivacyAuthorization 已经显示了隐私弹窗 + }) + + // 关闭选择弹窗 + this.$emit('close') } } } @@ -271,4 +417,72 @@ export default { } } } + +// ========== 隐私协议弹窗样式(新增) ========== +.privacy-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; +} + +.privacy-modal-content { + width: 560rpx; + background-color: #fff; + border-radius: 24rpx; + padding: 48rpx 32rpx 32rpx; + text-align: center; +} + +.privacy-modal-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + margin-bottom: 24rpx; +} + +.privacy-modal-text { + font-size: 28rpx; + color: #666; + line-height: 1.5; + margin-bottom: 40rpx; +} + +.privacy-link { + color: #007aff; + text-decoration: underline; +} + +.privacy-agree-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: #fff; + border-radius: 48rpx; + height: 80rpx; + line-height: 80rpx; + font-size: 32rpx; + margin-bottom: 20rpx; + + &::after { + border: none; + } +} + +.privacy-cancel-btn { + background-color: #f5f5f5; + color: #666; + border-radius: 48rpx; + height: 80rpx; + line-height: 80rpx; + font-size: 32rpx; + + &::after { + border: none; + } +} \ No newline at end of file diff --git a/src/components/petOrder/call-modal.vue b/src/components/petOrder/call-modal.vue index 4e6bf75..fb1a7d1 100644 --- a/src/components/petOrder/call-modal.vue +++ b/src/components/petOrder/call-modal.vue @@ -15,6 +15,28 @@ + + + + + 隐私保护提示 + + 请阅读并同意 + 《用户隐私保护协议》 + 后,方可使用拨打电话功能 + + + + + @@ -27,30 +49,134 @@ export default { } }, data() { - return {}; + return { + showPrivacyModal: false, // 隐私协议弹窗 + pendingCall: false // 是否有待执行的拨号请求 + }; }, methods: { closeAction() { + this.showPrivacyModal = false this.$emit('close'); }, - callAction() { - if (this.phoneNumber) { - uni.makePhoneCall({ - phoneNumber: this.phoneNumber, - success: (res) => { - console.log(res); - this.$emit('close'); - }, - fail: (err) => { - console.log(err); + + // 打开隐私协议详情(供用户查看) + openPrivacyContract() { + // #ifdef MP-TOUTIAO + tt.openPrivacyContract({ + fail: (err) => { + console.error('打开隐私协议失败', err) + uni.showToast({ + title: '无法打开协议', + icon: 'none' + }) + } + }) + // #endif + }, + + // 用户同意隐私协议 + onAgreePrivacy() { + console.log('用户已同意隐私协议') + this.showPrivacyModal = false + uni.showToast({ + title: '已授权', + icon: 'success' + }) + // 同意后执行拨号 + this.doMakePhoneCall() + }, + + // 用户拒绝隐私协议 + onDisagreePrivacy() { + this.showPrivacyModal = false + uni.showToast({ + title: '未授权,无法拨号', + icon: 'none' + }) + }, + + // 检查隐私授权状态 + checkPrivacyAndCall() { + // #ifdef MP-TOUTIAO + tt.getPrivacySetting({ + success: (res) => { + console.log('隐私授权状态:', res) + if (res.needAuthorization) { + // 未授权,显示隐私弹窗 + this.showPrivacyModal = true + } else { + // 已授权,直接拨号 + this.doMakePhoneCall() } - }) - } else { + }, + fail: (err) => { + console.error('获取隐私设置失败', err) + // 降级处理:直接拨号 + this.doMakePhoneCall() + } + }) + // #endif + + // #ifndef MP-TOUTIAO + // 非抖音平台直接拨号 + this.doMakePhoneCall() + // #endif + }, + + // 实际拨号方法 + doMakePhoneCall() { + if (!this.phoneNumber) { uni.showToast({ title: '电话号码为空', icon: 'none' }) + return; } + + uni.makePhoneCall({ + phoneNumber: this.phoneNumber, + success: (res) => { + console.log('拨号成功', res); + this.$emit('close'); + }, + fail: (err) => { + console.error('拨号失败', err); + // 拨号失败时,让用户手动复制 + uni.showModal({ + title: '客服电话', + content: this.phoneNumber, + confirmText: '复制', + cancelText: '取消', + success: (res) => { + if (res.confirm) { + uni.setClipboardData({ + data: this.phoneNumber, + success: () => { + uni.showToast({ + title: '电话已复制', + icon: 'success' + }) + } + }) + } + } + }) + } + }); + }, + + callAction() { + if (!this.phoneNumber) { + uni.showToast({ + title: '电话号码为空', + icon: 'none' + }) + return; + } + + // 检查隐私授权并拨号 + this.checkPrivacyAndCall() } }, } @@ -115,4 +241,72 @@ export default { } } } - + +// 隐私协议弹窗样式 +.privacy-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; +} + +.privacy-modal-content { + width: 560rpx; + background-color: #fff; + border-radius: 24rpx; + padding: 48rpx 32rpx 32rpx; + text-align: center; +} + +.privacy-modal-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + margin-bottom: 24rpx; +} + +.privacy-modal-text { + font-size: 28rpx; + color: #666; + line-height: 1.5; + margin-bottom: 40rpx; +} + +.privacy-link { + color: #007aff; + text-decoration: underline; +} + +.privacy-agree-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: #fff; + border-radius: 48rpx; + height: 80rpx; + line-height: 80rpx; + font-size: 32rpx; + margin-bottom: 20rpx; + + &::after { + border: none; + } +} + +.privacy-cancel-btn { + background-color: #f5f5f5; + color: #666; + border-radius: 48rpx; + height: 80rpx; + line-height: 80rpx; + font-size: 32rpx; + + &::after { + border: none; + } +} + \ No newline at end of file