| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <template>
- <div
- v-if="modelValue"
- class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
- @click.self="closeDialog"
- >
- <div
- class="bg-surface border border-white/10 rounded-2xl p-6 w-full max-w-md mx-4"
- >
- <div class="text-center mb-4">
- <h3 class="text-lg font-semibold text-white/90 mb-2">分享链接</h3>
- <p class="text-sm text-white/70">将链接分享给朋友,每天最多获得三部免费观看</p>
- </div>
- <!-- 分享链接显示区域 -->
- <div class="mb-4">
- <label class="block text-sm text-white/70 mb-2">分享链接:</label>
- <div class="flex items-center gap-2">
- <input
- :value="shareUrl"
- readonly
- class="flex-1 px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white/90 text-sm"
- />
- <button
- @click="copyShareLink"
- class="px-4 py-2 bg-brand text-slate-900 rounded-lg hover:bg-brand/90 transition text-sm font-medium"
- >
- 复制
- </button>
- </div>
- </div>
- <!-- 分享提示 -->
- <div class="mb-4 p-3 bg-green-500/10 rounded-lg border border-green-500/20">
- <p class="text-xs text-green-400">
- 💡 提示:朋友通过此链接访问并观看视频,即可计入您的分享次数
- </p>
- </div>
- <!-- 操作按钮 -->
- <div class="flex justify-center">
- <button
- @click="closeDialog"
- class="px-6 py-2 border border-white/20 text-white/70 rounded-lg hover:bg-white/5 transition"
- >
- 关闭
- </button>
- </div>
- </div>
- <!-- 成功提示弹窗 -->
- <div
- v-if="showSuccessToast"
- class="fixed inset-0 bg-black/50 flex items-center justify-center z-[9999]"
- @click.self="showSuccessToast = false"
- >
- <div class="bg-surface border border-white/10 rounded-2xl p-6 w-full max-w-sm mx-4 text-center">
- <!-- 成功图标 -->
- <div class="mb-4">
- <div class="w-12 h-12 mx-auto bg-green-500/20 rounded-full flex items-center justify-center">
- <svg class="w-6 h-6 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
- </svg>
- </div>
- </div>
- <!-- 成功信息 -->
- <h3 class="text-lg font-semibold text-white/90 mb-2">复制成功</h3>
- <p class="text-sm text-white/70 mb-6">{{ successMessage }}</p>
- <!-- 确认按钮 -->
- <button
- @click="showSuccessToast = false"
- class="w-full px-4 py-2 bg-brand text-slate-900 rounded-lg hover:bg-brand/90 transition"
- >
- 确定
- </button>
- </div>
- </div>
- <!-- 错误提示弹窗 -->
- <div
- v-if="showErrorToast"
- class="fixed inset-0 bg-black/50 flex items-center justify-center z-[9999]"
- @click.self="showErrorToast = false"
- >
- <div class="bg-surface border border-white/10 rounded-2xl p-6 w-full max-w-sm mx-4 text-center">
- <!-- 错误图标 -->
- <div class="mb-4">
- <div class="w-12 h-12 mx-auto bg-red-500/20 rounded-full flex items-center justify-center">
- <svg class="w-6 h-6 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"/>
- </svg>
- </div>
- </div>
- <!-- 错误信息 -->
- <h3 class="text-lg font-semibold text-white/90 mb-2">复制失败</h3>
- <p class="text-sm text-white/70 mb-6">{{ errorMessage }}</p>
- <!-- 确认按钮 -->
- <button
- @click="showErrorToast = false"
- class="w-full px-4 py-2 bg-brand text-slate-900 rounded-lg hover:bg-brand/90 transition"
- >
- 确定
- </button>
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, watch, ref } from 'vue';
- import { generateShareLink } from '@/services/shareApi';
- import { useUserStore } from '@/store/user';
- const props = defineProps<{
- modelValue: boolean;
- shareUrl?: string;
- shareTitle?: string;
- resourceId?: string;
- }>();
- const emit = defineEmits<{
- (e: 'update:modelValue', value: boolean): void;
- (e: 'success', message: string): void;
- (e: 'error', message: string): void;
- }>();
- const userStore = useUserStore();
- // 提示弹窗状态
- const showSuccessToast = ref(false);
- const showErrorToast = ref(false);
- const successMessage = ref('');
- const errorMessage = ref('');
- // 计算分享链接
- const shareUrl = computed(() => {
- console.log('🔄 shareUrl 计算属性执行:', {
- shareUrl: props.shareUrl,
- resourceId: props.resourceId,
- userId: userStore.userInfo?.id
- });
-
- if (props.shareUrl) {
- return props.shareUrl + "&inviter=" + userStore.userInfo?.id + "&resource=" + props.resourceId;
- }
-
- // 如果有resourceId,生成带分享参数的链接
- if (props.resourceId && userStore.userInfo?.id) {
- const generatedUrl = generateShareLink(userStore.userInfo.id, props.resourceId);
- console.log('✅ 生成分享链接:', generatedUrl);
- return generatedUrl;
- }
-
- console.log('⚠️ 使用默认URL:', window.location.href);
- return window.location.href;
- });
- // 关闭弹窗
- const closeDialog = () => {
- emit('update:modelValue', false);
- };
- // 复制分享链接
- const copyShareLink = async () => {
- try {
- // 检查是否支持 Clipboard API
- if (navigator.clipboard && navigator.clipboard.writeText) {
- await navigator.clipboard.writeText(shareUrl.value);
- showSuccessMessage('链接已复制到剪贴板!');
- } else {
- // 降级方案:使用传统的复制方法
- fallbackCopyToClipboard(shareUrl.value);
- }
- } catch (error) {
- console.error('复制失败:', error);
- // 尝试降级方案
- try {
- fallbackCopyToClipboard(shareUrl.value);
- } catch (fallbackError) {
- console.error('降级复制也失败:', fallbackError);
- showErrorMessage('复制失败,请手动复制链接');
- }
- }
- };
- // 降级复制方案
- const fallbackCopyToClipboard = (text: string) => {
- // 创建临时文本区域
- const textArea = document.createElement('textarea');
- textArea.value = text;
- textArea.style.position = 'fixed';
- textArea.style.left = '-999999px';
- textArea.style.top = '-999999px';
- document.body.appendChild(textArea);
-
- try {
- // 选择文本
- textArea.focus();
- textArea.select();
- textArea.setSelectionRange(0, 99999); // 移动端支持
-
- // 执行复制命令
- const successful = document.execCommand('copy');
- document.body.removeChild(textArea);
-
- if (successful) {
- showSuccessMessage('链接已复制到剪贴板!');
- } else {
- throw new Error('execCommand failed');
- }
- } catch (error) {
- document.body.removeChild(textArea);
- throw error;
- }
- };
- // 显示成功消息
- const showSuccessMessage = (message: string) => {
- successMessage.value = message;
- showSuccessToast.value = true;
- // 不发送事件给父组件,避免重复提示
- };
- // 显示错误消息
- const showErrorMessage = (message: string) => {
- errorMessage.value = message;
- showErrorToast.value = true;
- // 不发送事件给父组件,避免重复提示
- };
- // 移除分享行为记录逻辑
- // 分享者点击分享按钮时不需要调用recordShare接口
- // 只有被分享者点击分享链接时才调用recordShareClick接口
- // 监听弹窗显示状态(移除自动记录分享行为)
- watch(() => props.modelValue, (newVal) => {
- if (newVal) {
- // 弹窗打开时,确保用户信息已加载
- console.log('ShareDialog 打开,用户信息:', userStore.userInfo);
- console.log('resourceId:', props.resourceId);
- console.log('生成的分享链接:', shareUrl.value);
- }
- });
- </script>
|