185 lines
5.1 KiB
TypeScript
185 lines
5.1 KiB
TypeScript
|
|
/**
|
|||
|
|
* 分享工具函数
|
|||
|
|
* 支持移动浏览器原生分享 API 和 WhatsApp 分享
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
interface ShareData {
|
|||
|
|
title?: string
|
|||
|
|
text?: string
|
|||
|
|
url?: string
|
|||
|
|
files?: File[]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查是否支持 Web Share API
|
|||
|
|
*/
|
|||
|
|
export function isWebShareSupported(): boolean {
|
|||
|
|
return typeof navigator !== 'undefined' && 'share' in navigator
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 使用 Web Share API 进行分享(移动浏览器原生分享)
|
|||
|
|
* @param data 分享数据
|
|||
|
|
*/
|
|||
|
|
async function shareWithWebAPI(data: ShareData): Promise<void> {
|
|||
|
|
if (!isWebShareSupported()) {
|
|||
|
|
throw new Error('Web Share API is not supported')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// Web Share API 只支持 title, text, url 和 files
|
|||
|
|
const shareData: ShareData = {}
|
|||
|
|
|
|||
|
|
if (data.title) shareData.title = data.title
|
|||
|
|
if (data.text) shareData.text = data.text
|
|||
|
|
if (data.url) shareData.url = data.url
|
|||
|
|
if (data.files && data.files.length > 0) shareData.files = data.files
|
|||
|
|
|
|||
|
|
await navigator.share(shareData)
|
|||
|
|
} catch (error: any) {
|
|||
|
|
// 用户取消分享时,会抛出 AbortError,这是正常情况
|
|||
|
|
if (error.name !== 'AbortError') {
|
|||
|
|
console.error('分享失败:', error)
|
|||
|
|
throw error
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分享到 WhatsApp(回退方案)
|
|||
|
|
* @param text 分享的文本内容
|
|||
|
|
* @param url 分享的链接(可选)
|
|||
|
|
*/
|
|||
|
|
export function shareToWhatsApp(text: string, url?: string): void {
|
|||
|
|
const shareText = url ? `${text} ${url}` : text
|
|||
|
|
// WhatsApp Web API: https://wa.me/?text=
|
|||
|
|
const encodedText = encodeURIComponent(shareText)
|
|||
|
|
const whatsappUrl = `https://wa.me/?text=${encodedText}`
|
|||
|
|
|
|||
|
|
// 打开 WhatsApp 分享链接
|
|||
|
|
window.open(whatsappUrl, '_blank')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 通用分享函数(优先使用 Web Share API,不支持则回退到 WhatsApp)
|
|||
|
|
* @param options 分享选项
|
|||
|
|
*/
|
|||
|
|
export async function share(options: {
|
|||
|
|
title?: string
|
|||
|
|
text?: string
|
|||
|
|
url?: string
|
|||
|
|
files?: File[]
|
|||
|
|
fallbackToWhatsApp?: boolean
|
|||
|
|
}): Promise<void> {
|
|||
|
|
const { title, text, url, files, fallbackToWhatsApp = true } = options
|
|||
|
|
|
|||
|
|
// 如果支持 Web Share API,优先使用
|
|||
|
|
if (isWebShareSupported() && !files) {
|
|||
|
|
try {
|
|||
|
|
await shareWithWebAPI({ title, text, url })
|
|||
|
|
return
|
|||
|
|
} catch (error) {
|
|||
|
|
// 如果分享失败且允许回退,则使用 WhatsApp
|
|||
|
|
if (fallbackToWhatsApp) {
|
|||
|
|
const shareText = [title, text, url].filter(Boolean).join('\n\n')
|
|||
|
|
shareToWhatsApp(shareText)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
throw error
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果不支持 Web Share API 或需要分享文件,使用 WhatsApp
|
|||
|
|
if (fallbackToWhatsApp) {
|
|||
|
|
const shareText = [title, text, url].filter(Boolean).join('\n\n')
|
|||
|
|
shareToWhatsApp(shareText)
|
|||
|
|
} else {
|
|||
|
|
throw new Error('Web Share API is not supported and fallback is disabled')
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分享当前页面(优先使用原生分享,不支持则回退到 WhatsApp)
|
|||
|
|
* @param title 分享的标题
|
|||
|
|
* @param description 分享的描述(可选)
|
|||
|
|
*/
|
|||
|
|
export async function shareCurrentPage(title: string, description?: string): Promise<void> {
|
|||
|
|
const currentUrl = window.location.href
|
|||
|
|
await share({
|
|||
|
|
title,
|
|||
|
|
text: description,
|
|||
|
|
url: currentUrl,
|
|||
|
|
fallbackToWhatsApp: true
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分享图片(优先使用原生分享,不支持则回退到 WhatsApp)
|
|||
|
|
* @param imageUrl 图片链接
|
|||
|
|
* @param title 分享的标题
|
|||
|
|
* @param description 分享的描述(可选)
|
|||
|
|
*/
|
|||
|
|
export async function shareImage(imageUrl: string, title: string, description?: string): Promise<void> {
|
|||
|
|
console.log('1',imageUrl,'2',title)
|
|||
|
|
const currentUrl = window.location.href
|
|||
|
|
const text = description
|
|||
|
|
? `${description}\n\n查看图片: ${imageUrl}`
|
|||
|
|
: `查看图片: ${imageUrl}`
|
|||
|
|
|
|||
|
|
await share({
|
|||
|
|
title,
|
|||
|
|
text,
|
|||
|
|
url: currentUrl,
|
|||
|
|
fallbackToWhatsApp: true
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分享图片文件(使用 Web Share API,支持直接分享图片文件)
|
|||
|
|
* @param imageFile 图片文件
|
|||
|
|
* @param title 分享的标题(可选)
|
|||
|
|
* @param text 分享的文本(可选)
|
|||
|
|
*/
|
|||
|
|
export async function shareImageFile(imageFile: File, title?: string, text?: string): Promise<void> {
|
|||
|
|
if (!isWebShareSupported()) {
|
|||
|
|
// 如果不支持文件分享,可以尝试将文件转换为 URL 后分享
|
|||
|
|
const imageUrl = URL.createObjectURL(imageFile)
|
|||
|
|
await shareImage(imageUrl, title || '分享图片', text)
|
|||
|
|
URL.revokeObjectURL(imageUrl)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
await shareWithWebAPI({
|
|||
|
|
title,
|
|||
|
|
text,
|
|||
|
|
files: [imageFile]
|
|||
|
|
})
|
|||
|
|
} catch (error) {
|
|||
|
|
// 如果分享失败,回退到 URL 方式
|
|||
|
|
const imageUrl = URL.createObjectURL(imageFile)
|
|||
|
|
await shareImage(imageUrl, title || '分享图片', text)
|
|||
|
|
URL.revokeObjectURL(imageUrl)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分享当前页面到 WhatsApp(兼容旧版本,推荐使用 shareCurrentPage)
|
|||
|
|
* @param title 分享的标题
|
|||
|
|
* @param description 分享的描述(可选)
|
|||
|
|
*/
|
|||
|
|
export async function shareCurrentPageToWhatsApp(title: string, description?: string): Promise<void> {
|
|||
|
|
await shareCurrentPage(title, description)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分享图片到 WhatsApp(兼容旧版本,推荐使用 shareImage)
|
|||
|
|
* @param imageUrl 图片链接
|
|||
|
|
* @param title 分享的标题
|
|||
|
|
* @param description 分享的描述(可选)
|
|||
|
|
*/
|
|||
|
|
export async function shareImageToWhatsApp(imageUrl: string, title: string, description?: string): Promise<void> {
|
|||
|
|
await shareImage(imageUrl, title, description)
|
|||
|
|
}
|
|||
|
|
|