|
@@ -128,6 +128,53 @@
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 分享面板 -->
|
|
|
|
|
+ <view v-if="showSharePanel" class="share-picker" @click="showSharePanel = false">
|
|
|
|
|
+ <view class="share-content" @click.stop>
|
|
|
|
|
+ <!-- 分享卡片预览 -->
|
|
|
|
|
+ <view class="share-card-preview">
|
|
|
|
|
+ <view class="share-cover">
|
|
|
|
|
+ <text class="share-cover-icon">🎵</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="share-info">
|
|
|
|
|
+ <text class="share-title">{{ shareCard.title || 'AI 有声书' }}</text>
|
|
|
|
|
+ <text class="share-desc">{{ shareCard.description || '精彩内容,快来听听' }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <text class="share-title-text">分享到</text>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="share-options">
|
|
|
|
|
+ <view class="share-option" @click="shareToWechat">
|
|
|
|
|
+ <text class="share-option-icon">💬</text>
|
|
|
|
|
+ <text class="share-option-label">微信好友</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="share-option" @click="shareToMoments">
|
|
|
|
|
+ <text class="share-option-icon">⭕</text>
|
|
|
|
|
+ <text class="share-option-label">朋友圈</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="share-option" @click="shareToWeibo">
|
|
|
|
|
+ <text class="share-option-icon">📢</text>
|
|
|
|
|
+ <text class="share-option-label">微博</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="share-option" @click="shareToQQ">
|
|
|
|
|
+ <text class="share-option-icon">🐧</text>
|
|
|
|
|
+ <text class="share-option-label">QQ</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="share-actions">
|
|
|
|
|
+ <button class="share-action-btn" @click="copyShareLink">
|
|
|
|
|
+ <text class="share-action-icon">🔗</text>
|
|
|
|
|
+ <text>复制链接</text>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="share-action-btn" @click="showSharePanel = false">
|
|
|
|
|
+ <text>取消</text>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
@@ -145,8 +192,10 @@ const audioId = ref('');
|
|
|
const audio = ref<AudioItem | null>(null);
|
|
const audio = ref<AudioItem | null>(null);
|
|
|
const showRatePicker = ref(false);
|
|
const showRatePicker = ref(false);
|
|
|
const showTimerPicker = ref(false);
|
|
const showTimerPicker = ref(false);
|
|
|
|
|
+const showSharePanel = ref(false);
|
|
|
const savedProgress = ref(0); // 保存的历史进度
|
|
const savedProgress = ref(0); // 保存的历史进度
|
|
|
const showResumePrompt = ref(false); // 显示继续播放提示
|
|
const showResumePrompt = ref(false); // 显示继续播放提示
|
|
|
|
|
+const shareCard = ref({ title: '', description: '', imageUrl: '', link: '' });
|
|
|
|
|
|
|
|
// 定时关闭状态
|
|
// 定时关闭状态
|
|
|
const timerDuration = ref(0); // 定时时长(秒),0表示未设置
|
|
const timerDuration = ref(0); // 定时时长(秒),0表示未设置
|
|
@@ -477,28 +526,116 @@ function handleDownload() {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 分享
|
|
|
|
|
-function handleShare() {
|
|
|
|
|
- // H5 使用 Web Share API
|
|
|
|
|
- if (typeof navigator !== 'undefined' && navigator.share) {
|
|
|
|
|
- navigator.share({
|
|
|
|
|
- title: audio.value?.title || 'AI 有声书',
|
|
|
|
|
- url: window.location.href,
|
|
|
|
|
- }).catch(() => {
|
|
|
|
|
- // 用户取消或分享失败,降级到复制链接
|
|
|
|
|
- copyShareLink();
|
|
|
|
|
|
|
+// 分享 - 打开分享面板
|
|
|
|
|
+async function handleShare() {
|
|
|
|
|
+ if (!audio.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 获取分享卡片信息
|
|
|
|
|
+ const result = await get<any>(`/share?audioId=${audio.value.id || audio.value._id}`);
|
|
|
|
|
+ if (result) {
|
|
|
|
|
+ shareCard.value = result;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ shareCard.value = {
|
|
|
|
|
+ title: audio.value.title || 'AI 有声书',
|
|
|
|
|
+ description: (audio.value.summary || audio.value.text || '').slice(0, 50) + '...',
|
|
|
|
|
+ imageUrl: '',
|
|
|
|
|
+ link: `${window.location.origin}/#/pages/player/index?id=${audio.value._id}`,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ shareCard.value = {
|
|
|
|
|
+ title: audio.value.title || 'AI 有声书',
|
|
|
|
|
+ description: (audio.value.summary || audio.value.text || '').slice(0, 50) + '...',
|
|
|
|
|
+ imageUrl: '',
|
|
|
|
|
+ link: `${window.location.origin}/#/pages/player/index?id=${audio.value._id}`,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ showSharePanel.value = true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分享到微信好友
|
|
|
|
|
+function shareToWechat() {
|
|
|
|
|
+ showSharePanel.value = false;
|
|
|
|
|
+ // 检查是否有微信JSSDK
|
|
|
|
|
+ if ((window as any).wx) {
|
|
|
|
|
+ // 使用微信JSSDK分享
|
|
|
|
|
+ (window as any).wx.updateAppMessageShareData({
|
|
|
|
|
+ title: shareCard.value.title,
|
|
|
|
|
+ desc: shareCard.value.description,
|
|
|
|
|
+ link: shareCard.value.link,
|
|
|
|
|
+ success: () => {
|
|
|
|
|
+ uni.showToast({ title: '分享成功', icon: 'success' });
|
|
|
|
|
+ trackShare('wechat');
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: () => {
|
|
|
|
|
+ copyShareLink();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 降级到复制链接
|
|
|
|
|
+ uni.showToast({ title: '请使用微信打开分享', icon: 'none' });
|
|
|
|
|
+ setTimeout(() => copyShareLink(), 1500);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分享到朋友圈
|
|
|
|
|
+function shareToMoments() {
|
|
|
|
|
+ showSharePanel.value = false;
|
|
|
|
|
+ if ((window as any).wx) {
|
|
|
|
|
+ (window as any).wx.updateTimelineShareData({
|
|
|
|
|
+ title: shareCard.value.title,
|
|
|
|
|
+ link: shareCard.value.link,
|
|
|
|
|
+ success: () => {
|
|
|
|
|
+ uni.showToast({ title: '分享成功', icon: 'success' });
|
|
|
|
|
+ trackShare('moments');
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: () => {
|
|
|
|
|
+ copyShareLink();
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
} else {
|
|
} else {
|
|
|
- // 其他平台:复制链接到剪贴板
|
|
|
|
|
- copyShareLink();
|
|
|
|
|
|
|
+ uni.showToast({ title: '请使用微信打开分享', icon: 'none' });
|
|
|
|
|
+ setTimeout(() => copyShareLink(), 1500);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分享到微博
|
|
|
|
|
+function shareToWeibo() {
|
|
|
|
|
+ showSharePanel.value = false;
|
|
|
|
|
+ const shareUrl = `https://service.weibo.com/share/share.php?title=${encodeURIComponent(shareCard.value.title)}&url=${encodeURIComponent(shareCard.value.link)}`;
|
|
|
|
|
+ window.open(shareUrl, '_blank');
|
|
|
|
|
+ trackShare('weibo');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分享到QQ
|
|
|
|
|
+function shareToQQ() {
|
|
|
|
|
+ showSharePanel.value = false;
|
|
|
|
|
+ const shareUrl = `https://connect.qq.com/widget/shareqq/index.html?title=${encodeURIComponent(shareCard.value.title)}&url=${encodeURIComponent(shareCard.value.link)}&desc=${encodeURIComponent(shareCard.value.description)}`;
|
|
|
|
|
+ window.open(shareUrl, '_blank');
|
|
|
|
|
+ trackShare('qq');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 记录分享行为
|
|
|
|
|
+async function trackShare(platform: string) {
|
|
|
|
|
+ if (!audio.value) return;
|
|
|
|
|
+ try {
|
|
|
|
|
+ await post('/share/track', {
|
|
|
|
|
+ audioId: audio.value.id || audio.value._id,
|
|
|
|
|
+ platform: platform
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.log('记录分享失败:', error);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 复制链接
|
|
// 复制链接
|
|
|
function copyShareLink() {
|
|
function copyShareLink() {
|
|
|
|
|
+ showSharePanel.value = false;
|
|
|
if (!audio.value) return;
|
|
if (!audio.value) return;
|
|
|
-
|
|
|
|
|
- const shareUrl = `${window.location.origin}/#/pages/player/index?id=${audio.value._id}`;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ const shareUrl = shareCard.value.link || `${window.location.origin}/#/pages/player/index?id=${audio.value._id}`;
|
|
|
uni.setClipboardData({
|
|
uni.setClipboardData({
|
|
|
data: shareUrl,
|
|
data: shareUrl,
|
|
|
success: () => {
|
|
success: () => {
|
|
@@ -793,4 +930,141 @@ function copyShareLink() {
|
|
|
.resume-btn::after {
|
|
.resume-btn::after {
|
|
|
border: none;
|
|
border: none;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 分享面板 */
|
|
|
|
|
+.share-picker {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.6);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: flex-end;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-content {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ background: #1f2937;
|
|
|
|
|
+ border-radius: 32rpx 32rpx 0 0;
|
|
|
|
|
+ padding: 48rpx 32rpx 32rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-card-preview {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 24rpx;
|
|
|
|
|
+ padding: 24rpx;
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.05);
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ margin-bottom: 32rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-cover {
|
|
|
|
|
+ width: 120rpx;
|
|
|
|
|
+ height: 120rpx;
|
|
|
|
|
+ background: linear-gradient(135deg, #4f46e5 0%, #818cf8 100%);
|
|
|
|
|
+ border-radius: 12rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-cover-icon {
|
|
|
|
|
+ font-size: 48rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-info {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-title {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ margin-bottom: 8rpx;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-desc {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #9ca3af;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ display: -webkit-box;
|
|
|
|
|
+ -webkit-line-clamp: 2;
|
|
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-title-text {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin-bottom: 32rpx;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-options {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-around;
|
|
|
|
|
+ margin-bottom: 32rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-option {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 12rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-option-icon {
|
|
|
|
|
+ width: 96rpx;
|
|
|
|
|
+ height: 96rpx;
|
|
|
|
|
+ background: #374151;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ font-size: 40rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-option-label {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #9ca3af;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-actions {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 24rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-action-btn {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ height: 88rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ gap: 8rpx;
|
|
|
|
|
+ background: #374151;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-action-btn::after {
|
|
|
|
|
+ border: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.share-action-icon {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|