diff --git a/index.html b/index.html index 8172a46..148096a 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,15 @@ - Activities + Lane Crawford + + + + + + + +
diff --git a/src/utils/share.ts b/src/utils/share.ts new file mode 100644 index 0000000..8b87b6c --- /dev/null +++ b/src/utils/share.ts @@ -0,0 +1,209 @@ +/** + * 分享工具函数 + * 支持移动浏览器原生分享 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 { + 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 + const encodedText = encodeURIComponent(shareText) + const whatsappScheme = `whatsapp://send?text=${encodedText}` + const whatsappWebUrl = `https://wa.me/?text=${encodedText}` + const isMobile = typeof navigator !== 'undefined' && /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent) + + if (typeof window === 'undefined') return + + if (isMobile) { + // 优先尝试调用已安装的 WhatsApp 应用,失败后回退到 Web 版本 + let didFallback = false + const fallbackTimer = window.setTimeout(() => { + didFallback = true + window.location.href = whatsappWebUrl + }, 1500) + + try { + window.location.href = whatsappScheme + } catch (error) { + window.clearTimeout(fallbackTimer) + window.location.href = whatsappWebUrl + } + + // 某些浏览器会在成功唤起 App 时终止脚本,无需额外处理 + return + } + + // 桌面端或不支持 scheme 的环境直接打开 WhatsApp Web + window.open(whatsappWebUrl, '_blank') +} + +/** + * 通用分享函数(优先使用 Web Share API,不支持则回退到 WhatsApp) + * @param options 分享选项 + */ +export async function share(options: { + title?: string + text?: string + url?: string + files?: File[] + fallbackToWhatsApp?: boolean +}): Promise { + 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 { + 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 { + 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 { + if (!isWebShareSupported()) { + throw new Error('WEB_SHARE_UNSUPPORTED') + } + if (typeof navigator.canShare === 'function' && !navigator.canShare({ files: [imageFile] })) { + throw new Error('WEB_SHARE_FILE_UNSUPPORTED') + } + + await shareWithWebAPI({ + title, + text, + files: [imageFile] + }) +} + +/** + * 将远程图片转换为 File 对象,便于提前缓存后再触发分享 + * @param imageUrl 图片链接 + * @param fileName 文件名(可选) + */ +export async function createImageFileFromUrl(imageUrl: string, fileName?: string): Promise { + const response = await fetch(imageUrl) + const blob = await response.blob() + const name = fileName || imageUrl.split('/').pop() || 'share-image.jpg' + return new File([blob], name, { type: blob.type || 'image/jpeg' }) +} + +/** + * 分享当前页面到 WhatsApp(兼容旧版本,推荐使用 shareCurrentPage) + * @param title 分享的标题 + * @param description 分享的描述(可选) + */ +export async function shareCurrentPageToWhatsApp(title: string, description?: string): Promise { + await shareCurrentPage(title, description) +} + +/** + * 分享图片到 WhatsApp(兼容旧版本,推荐使用 shareImage) + * @param imageUrl 图片链接 + * @param title 分享的标题 + * @param description 分享的描述(可选) + */ +export async function shareImageToWhatsApp(imageUrl: string, title: string, description?: string): Promise { + await shareImage(imageUrl, title, description) +} + diff --git a/src/views/Workshop/creation/creation-list.vue b/src/views/Workshop/creation/creation-list.vue index 8f9cbff..1fa409a 100644 --- a/src/views/Workshop/creation/creation-list.vue +++ b/src/views/Workshop/creation/creation-list.vue @@ -1,334 +1,367 @@ diff --git a/src/views/Workshop/home.vue b/src/views/Workshop/home.vue index d16c8da..4fc371f 100644 --- a/src/views/Workshop/home.vue +++ b/src/views/Workshop/home.vue @@ -110,12 +110,14 @@ defineExpose({}) padding: 0 7.4rem; gap: 4.8rem; > .item{ - width: 44.2rem; - height: 41.6rem; + // width: 44.2rem; + // height: 41.6rem; + height: auto; + width: calc(50% - 4.8rem / 2); > img{ width: 100%; height: 100%; - object-fit: cover; + object-fit: contain; } } }