hookehuyr

feat(咨询弹窗): 将单联系人改为多联系人列表并优化拨打交互

- 移除富文本咨询信息和复制功能
- 新增联系人列表展示,支持点击姓名或号码直接拨打
- 优化电话拨打逻辑,支持传入特定号码
......@@ -33,11 +33,9 @@ https://oa-dev.onwall.cn/f/mlaj
- 课程详情页咨询弹窗(Mock)
- 入口:详情页顶部快捷操作中的“咨询”按钮。
- 展示:底部弹出层,仅底部关闭按钮;内容支持富文本展示。
- 电话:显示咨询电话;点击即可直接拨打(`tel:`)。
- 咨询信息:富文本区域点击即可复制到剪切板;复制成功后提示。
- 图片压缩:富文本中若包含 `cdn.ipadbiz.cn` 图片,使用 `?imageMogr2/thumbnail/200x/strip/quality/70` 参数。
- 位置:`/src/views/courses/CourseDetailPage.vue`,“咨询弹窗”模板与交互逻辑(`open_consult_dialog``close_consult_dialog``call_phone``copy_consult_info`)。
- 展示:底部弹出层,仅底部关闭按钮;展示联系人列表,可点击名称或号码直接拨打(`tel:`)。
- 联系人:支持多个联系人,展示姓名与号码;电话号码使用绿色高亮;联系人与号码字体大小一致。
- 位置:`/src/views/courses/CourseDetailPage.vue`,“咨询弹窗”模板与交互逻辑(`open_consult_dialog``close_consult_dialog``consult_contacts``call_phone(phone)`)。
- 购买流程环境校验
- 行为:仅对非免费课程在详情页点击“购买”时进行校验;生产环境下必须为微信内置浏览器(`wxInfo().isWeiXin`)。
......
......@@ -342,23 +342,20 @@
<van-icon name="cross" @click="close_consult_dialog" />
</div>
<!-- 电话信息:点击直接拨打 -->
<!-- 联系人列表:点击名称直接拨打 -->
<div class="bg-gray-50 border border-gray-200 rounded-lg p-3 mb-4">
<div class="flex items-center justify-between">
<div class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500 mr-2" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h2.28a2 2 0 011.789 1.106l1.152 2.305a2 2 0 01-.42 2.317L9.384 10.09a16.001 16.001 0 006.526 6.526l1.356-1.102a2 2 0 012.317-.42l2.305 1.152A2 2 0 0121 18.72V21a2 2 0 01-2 2h-1a18 18 0 01-17-17V5z" />
</svg>
<span class="text-gray-700">联系电话</span>
</div>
<a class="text-green-600 font-medium" :href="`tel:${consult_phone}`" @click.prevent="call_phone">{{ consult_phone }}</a>
<div class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500 mr-2" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h2.28a2 2 0 011.789 1.106l1.152 2.305a2 2 0 01-.42 2.317L9.384 10.09a16.001 16.001 0 006.526 6.526l1.356-1.102a2 2 0 012.317-.42l2.305 1.152A2 2 0 0121 18.72V21a2 2 0 01-2 2h-1a18 18 0 01-17-17V5z" />
</svg>
<span class="text-gray-700">联系人</span>
</div>
</div>
<!-- 富文本咨询信息:点击复制到剪切板 -->
<div class="bg-white border border-gray-100 rounded-lg p-3">
<div class="text-gray-700 text-sm leading-6" v-html="consult_html" @click="copy_consult_info"></div>
<div class="text-xs text-gray-400 mt-2">提示:点击上方任意文字即可复制咨询内容</div>
<ul class="mt-2 divide-y divide-gray-200">
<li v-for="(c, idx) in consult_contacts" :key="idx" class="flex items-center justify-between py-2">
<a class="text-gray-800 text-sm" :href="`tel:${c.phone}`" @click.prevent="call_phone(c.phone)">{{ c.name }}</a>
<a class="text-green-600 text-sm" :href="`tel:${c.phone}`" @click.prevent="call_phone(c.phone)">{{ c.phone }}</a>
</li>
</ul>
</div>
<!-- 底部关闭按钮(唯一操作) -->
......@@ -545,21 +542,14 @@ const checkInSuccess = ref(false)
const show_consult_dialog = ref(false)
/**
* 咨询联系电话(Mock 数据)
* @type {import('vue').Ref<string>}
* 咨询联系人列表(Mock 数据)
* 说明:支持多个联系人,点击名称直接拨号
* @type {import('vue').Ref<Array<{name:string, phone:string}>>}
*/
const consult_phone = ref('400-888-8888')
/**
* 咨询富文本内容(Mock 数据)
* 说明:示例中包含来自 cdn.ipadbiz.cn 的图片,带有压缩参数
* @type {import('vue').Ref<string>}
*/
const consult_html = ref(
'<p><strong>课程咨询说明:</strong>如需了解课程安排、报名流程、发票开具等信息,请联系课程顾问。</p>' +
'<p>可通过电话或复制下方咨询信息进行沟通。</p>' +
'<p><img src="https://cdn.ipadbiz.cn/images/consult_demo.png?imageMogr2/thumbnail/200x/strip/quality/70" alt="咨询示例" style="max-width:100%;border-radius:8px;"/></p>'
)
const consult_contacts = ref([
{ name: '课程顾问A', phone: '400-888-8888' },
{ name: '课程顾问B', phone: '13800000000' }
])
/**
* 打开咨询弹窗
......@@ -578,50 +568,14 @@ const close_consult_dialog = () => {
}
/**
* 直接拨打咨询电话
* 直接拨打指定联系人电话
* @param {string} phone 电话号码
* @returns {void}
*/
const call_phone = () => {
const phone = consult_phone.value || ''
if (phone) {
window.location.href = `tel:${phone}`
}
}
/**
* 将富文本内容转换为纯文本
* @param {string} html 原始富文本 HTML 字符串
* @returns {string} 纯文本内容
*/
const strip_html = (html) => {
const text = (html || '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim()
return text
}
/**
* 复制咨询富文本信息为纯文本
* @returns {Promise<void>}
*/
const copy_consult_info = async () => {
const text = strip_html(consult_html.value)
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text)
} else {
const textarea = document.createElement('textarea')
textarea.value = text
textarea.style.position = 'fixed'
textarea.style.top = '-1000px'
document.body.appendChild(textarea)
textarea.focus()
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
}
showToast('咨询信息已复制')
} catch (err) {
console.error('复制失败: ', err)
showToast('复制失败,请稍后重试')
const call_phone = (phone) => {
const p = phone || ''
if (p) {
window.location.href = `tel:${p}`
}
}
......