97 lines
2.9 KiB
Vue
97 lines
2.9 KiB
Vue
<script setup lang="ts">
|
||
import { onMounted } from 'vue'
|
||
|
||
const props = defineProps<{
|
||
url: string
|
||
title?: string
|
||
desc?: string
|
||
imgUrl?: string
|
||
}>()
|
||
|
||
// 仅在客户端挂载后执行,避免 SSR 阶段访问 window/location
|
||
onMounted(async () => {
|
||
try {
|
||
console.log('[WxShare] mounted with props:', { ...props })
|
||
await loadWxSdk()
|
||
console.log('[WxShare] wx sdk loaded:', !!(window as any).wx)
|
||
const { appId, timestamp, nonceStr, signature } = await getWxConfig()
|
||
console.log('[WxShare] got config:', { appId, timestamp, nonceStr, signature: signature.slice(0, 8) + '...' })
|
||
setupShare(appId, timestamp, nonceStr, signature)
|
||
} catch (err) {
|
||
console.error('[WxShare] init error:', err)
|
||
}
|
||
})
|
||
|
||
function loadWxSdk(): Promise<void> {
|
||
console.log('loadWxSdk')
|
||
if (typeof window === 'undefined') return Promise.resolve()
|
||
if ((window as any).wx) return Promise.resolve()
|
||
return new Promise((resolve, reject) => {
|
||
const existing = document.getElementById('wx-jssdk') as HTMLScriptElement | null
|
||
if (existing && (window as any).wx) return resolve()
|
||
const script = existing ?? document.createElement('script')
|
||
if (!existing) {
|
||
script.id = 'wx-jssdk'
|
||
script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'
|
||
script.async = true
|
||
script.onload = () => resolve()
|
||
script.onerror = () => reject(new Error('Failed to load jweixin.js'))
|
||
document.head.appendChild(script)
|
||
} else {
|
||
script.onload = () => resolve()
|
||
script.onerror = () => reject(new Error('Failed to load jweixin.js'))
|
||
}
|
||
})
|
||
}
|
||
|
||
async function getWxConfig(): Promise<{ appId: string, timestamp: number, nonceStr: string, signature: string }> {
|
||
const currentUrl = encodeURIComponent((location.href.split('#')[0]) || location.href)
|
||
return await $fetch('/api/wechat/wx-config', { params: { url: currentUrl } })
|
||
}
|
||
|
||
function setupShare(appId: string, timestamp: number, nonceStr: string, signature: string) {
|
||
const wx = (window as any).wx
|
||
const shareTitle = props.title || document.title || ''
|
||
const shareDesc = props.desc || document.title || ''
|
||
const shareLink = props.url
|
||
const shareImg = props.imgUrl || '/images/default-blog.jpg'
|
||
|
||
wx.config({
|
||
debug: false,
|
||
appId,
|
||
timestamp,
|
||
nonceStr,
|
||
signature,
|
||
jsApiList: ['updateTimelineShareData', 'updateAppMessageShareData']
|
||
})
|
||
|
||
wx.ready(() => {
|
||
console.log('[WxShare] wx.ready')
|
||
wx.updateTimelineShareData({
|
||
title: shareTitle,
|
||
link: shareLink,
|
||
imgUrl: shareImg,
|
||
success: () => {}
|
||
})
|
||
wx.updateAppMessageShareData({
|
||
title: shareTitle,
|
||
desc: shareDesc,
|
||
link: shareLink,
|
||
imgUrl: shareImg,
|
||
success: () => {}
|
||
})
|
||
})
|
||
|
||
wx.error((e: unknown) => {
|
||
console.error('[WxShare] wx.error:', e)
|
||
})
|
||
}
|
||
|
||
|
||
</script>
|
||
|
||
<template>
|
||
<div style="display: none" />
|
||
<!-- 该组件无可视内容,仅用于初始化微信分享 -->
|
||
</template>
|