1374 lines
32 KiB
Vue
1374 lines
32 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="video-container" @touchstart="onTouchStart" @touchend="onTouchEnd">
|
|||
|
|
<video
|
|||
|
|
id="video-element"
|
|||
|
|
class="video-player"
|
|||
|
|
:src="videoUrl"
|
|||
|
|
:autoplay="autoplay"
|
|||
|
|
:muted="muted"
|
|||
|
|
:controls="false"
|
|||
|
|
loop
|
|||
|
|
object-fit="cover"
|
|||
|
|
@play="onVideoPlay"
|
|||
|
|
@pause="onVideoPause"
|
|||
|
|
@ended="onVideoEnd"
|
|||
|
|
@timeupdate="onTimeUpdate"
|
|||
|
|
@loadedmetadata="onVideoReady"
|
|||
|
|
@click="onVideoTap"
|
|||
|
|
></video>
|
|||
|
|
|
|||
|
|
<!-- 顶部控制栏 -->
|
|||
|
|
<view class="top-controls" :style="{ paddingTop: statusBarHeight + 'px' }">
|
|||
|
|
<view class="left-controls">
|
|||
|
|
<view class="back-btn" @click="onBack">
|
|||
|
|
<text class="icon-back">‹</text>
|
|||
|
|
</view>
|
|||
|
|
<text class="time-display">{{ currentTime }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 视频内容区域 -->
|
|||
|
|
<view class="video-content" @click="onPlayPause">
|
|||
|
|
<view :class="['play-indicator', isPlaying ? 'hide' : 'show']">
|
|||
|
|
<text class="play-icon">▶</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 底部信息区域 -->
|
|||
|
|
<view class="bottom-info">
|
|||
|
|
<!-- 文章加载状态 -->
|
|||
|
|
<view class="article-status" v-if="isLoadingArticle || articleError">
|
|||
|
|
<view class="loading-indicator" v-if="isLoadingArticle">
|
|||
|
|
<text class="loading-text">正在加载文章详情...</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="error-message" v-if="articleError">
|
|||
|
|
<text class="error-text">{{ articleError }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 创作者信息 -->
|
|||
|
|
<view class="creator-info">
|
|||
|
|
<image class="creator-avatar" :src="creatorAvatar" @click="onCreatorTap" />
|
|||
|
|
<view class="creator-details">
|
|||
|
|
<text class="creator-name">{{ creatorName }}</text>
|
|||
|
|
<view :class="['follow-btn', isFollowing ? 'following' : '']" @click="onFollow">
|
|||
|
|
{{ isFollowing ? '已关注' : '关注' }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 视频描述 -->
|
|||
|
|
<view class="video-info" v-if="videoDescription">
|
|||
|
|
<view :class="['video-description', isDescriptionExpanded ? 'expanded' : '']" @click="onToggleDescription">
|
|||
|
|
{{ videoDescription }}
|
|||
|
|
</view>
|
|||
|
|
<view class="expand-toggle" @click="onToggleDescription" v-if="videoDescription.length > 50">
|
|||
|
|
<text class="iconfont" :class="isDescriptionExpanded ? 'icon-xiangshang' : 'icon-xiangxia'"></text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 互动区域 -->
|
|||
|
|
<view class="interaction-area">
|
|||
|
|
<view class="like-section">
|
|||
|
|
<view :class="['like-btn', isLiked ? 'liked' : '']" @click="onLike">
|
|||
|
|
<text class="heart-icon">{{ isLiked ? '❤️' : '🤍' }}</text>
|
|||
|
|
</view>
|
|||
|
|
<text class="like-count">{{ likeCount }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="action-buttons">
|
|||
|
|
<view class="consult-btn" @click="onConsult">立即咨询</view>
|
|||
|
|
<view class="action-btn" @click="onCreateSimilar">做同款</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- AI生成内容标识 -->
|
|||
|
|
<view class="ai-notice">
|
|||
|
|
<text class="ai-notice-text">内容由AI生成</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 进度条 -->
|
|||
|
|
<view class="progress-bar">
|
|||
|
|
<view class="progress-track">
|
|||
|
|
<view class="progress-fill" :style="{ width: progress + '%' }"></view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 悬浮操作按钮 -->
|
|||
|
|
<view class="floating-actions">
|
|||
|
|
<view class="floating-btn download-btn" @click="onDownload">
|
|||
|
|
<text class="floating-label">下载</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="floating-btn share-btn" @click="onShare">
|
|||
|
|
<text class="floating-label">分享</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import api from '@/api/models-api.js';
|
|||
|
|
import { mapGetters } from 'vuex';
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
videoUrl: 'https://jxz.uj345.cc/videos/video1.mp4',
|
|||
|
|
currentTime: '00:25',
|
|||
|
|
progress: 45,
|
|||
|
|
isPlaying: false,
|
|||
|
|
autoplay: false,
|
|||
|
|
muted: false,
|
|||
|
|
creatorName: '开心海浪',
|
|||
|
|
creatorAvatar: '/static/images/creator-avatar.png',
|
|||
|
|
isFollowing: false,
|
|||
|
|
videoDescription: '女孩自然的姿势贴地快速飞行,飞向湖面,镜头跟随其后,女孩自然的姿势贴地快速飞行,飞向湖面,镜头跟随其后,女孩自然的姿势贴地快速飞行,飞向湖面,镜头跟随其后',
|
|||
|
|
isDescriptionExpanded: false,
|
|||
|
|
isLiked: false,
|
|||
|
|
likeCount: 2778,
|
|||
|
|
videoContext: null,
|
|||
|
|
isVideoReady: false,
|
|||
|
|
playPromise: null,
|
|||
|
|
articleData: null,
|
|||
|
|
isLoadingArticle: false,
|
|||
|
|
articleError: null,
|
|||
|
|
currentArticleId: null,
|
|||
|
|
touchStartY: 0,
|
|||
|
|
touchEndY: 0,
|
|||
|
|
isSwipeEnabled: true,
|
|||
|
|
statusBarHeight: 0,
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
computed: mapGetters(['chatUrl']),
|
|||
|
|
onLoad(options) {
|
|||
|
|
const articleId = options.id;
|
|||
|
|
this.setData({
|
|||
|
|
currentArticleId: articleId,
|
|||
|
|
});
|
|||
|
|
const sys = uni.getSystemInfoSync();
|
|||
|
|
const sbh = sys.statusBarHeight;
|
|||
|
|
this.statusBarHeight = (sbh && sbh > 0) ? sbh : (sys.platform === 'ios' ? 44 : 24);
|
|||
|
|
if (articleId) {
|
|||
|
|
console.log('开始加载文章详情,ID:', articleId);
|
|||
|
|
this.loadArticleDetail(articleId);
|
|||
|
|
} else {
|
|||
|
|
console.log('未提供文章ID,跳过文章详情加载');
|
|||
|
|
}
|
|||
|
|
setTimeout(() => {
|
|||
|
|
this.videoContext = uni.createVideoContext('video-element', this);
|
|||
|
|
this.setData({
|
|||
|
|
isVideoReady: true,
|
|||
|
|
});
|
|||
|
|
}, 1000);
|
|||
|
|
},
|
|||
|
|
onShow() {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
if (this.videoContext && this.isVideoReady) {
|
|||
|
|
this.safePlay();
|
|||
|
|
}
|
|||
|
|
}, 300);
|
|||
|
|
},
|
|||
|
|
onHide() {
|
|||
|
|
if (this.videoContext && this.isVideoReady) {
|
|||
|
|
this.safePause();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
sanitizeText(str) {
|
|||
|
|
if (!str || typeof str !== 'string') return '';
|
|||
|
|
try {
|
|||
|
|
// 去除所有 HTML 标签,避免 WXML 解析原始 `<` `>` 造成语法错误
|
|||
|
|
const noTags = str.replace(/<[^>]*>/g, '');
|
|||
|
|
// 保险处理:将残留的尖括号转义为实体
|
|||
|
|
return noTags.replace(/</g, '<').replace(/>/g, '>');
|
|||
|
|
} catch (e) {
|
|||
|
|
return String(str);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
// 处理头像URL,添加前缀
|
|||
|
|
getAvatarUrl(avatarUrl) {
|
|||
|
|
if (!avatarUrl || avatarUrl === '/static/images/avatar-default.png') {
|
|||
|
|
return '/static/images/avatar-default.png';
|
|||
|
|
}
|
|||
|
|
// 如果已经是完整URL,直接返回
|
|||
|
|
if (avatarUrl.startsWith('http://') || avatarUrl.startsWith('https://')) {
|
|||
|
|
return avatarUrl;
|
|||
|
|
}
|
|||
|
|
// 如果是相对路径,添加前缀
|
|||
|
|
const prefix = 'https://uthink2025.oss-cn-shanghai.aliyuncs.com/';
|
|||
|
|
// 如果URL已经以/开头,去掉开头的/
|
|||
|
|
const cleanUrl = avatarUrl.startsWith('/') ? avatarUrl.substring(1) : avatarUrl;
|
|||
|
|
return prefix + cleanUrl;
|
|||
|
|
},
|
|||
|
|
loadVideoData() {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
this.setData({
|
|||
|
|
videoUrl: '/videos/sample-video.mp4',
|
|||
|
|
});
|
|||
|
|
}, 500);
|
|||
|
|
},
|
|||
|
|
loadArticleDetail(articleId) {
|
|||
|
|
console.log('loadArticleDetail 被调用,参数:', articleId);
|
|||
|
|
this.setData({
|
|||
|
|
isLoadingArticle: true,
|
|||
|
|
articleError: null,
|
|||
|
|
});
|
|||
|
|
console.log('设置加载状态为 true');
|
|||
|
|
api.getArticleById(articleId).then(response => {
|
|||
|
|
console.log('API响应原始数据:', response);
|
|||
|
|
const data = response.data || response;
|
|||
|
|
console.log('文章详情数据:', data);
|
|||
|
|
const rawDesc = data.prompt || data.content || data.title || data.synopsis || this.videoDescription;
|
|||
|
|
const safeDesc = this.sanitizeText(rawDesc);
|
|||
|
|
|
|||
|
|
// 获取作者头像
|
|||
|
|
const authorAvatar = this.getAvatarUrl(data.authorAvatar || data.avatar || '');
|
|||
|
|
|
|||
|
|
// 获取作者名称
|
|||
|
|
const authorName = data.authorName || data.author || this.creatorName;
|
|||
|
|
|
|||
|
|
// 获取点赞数
|
|||
|
|
const likeCount = data.likeCount || data.visit || this.likeCount;
|
|||
|
|
|
|||
|
|
this.setData({
|
|||
|
|
articleData: data,
|
|||
|
|
isLoadingArticle: false,
|
|||
|
|
videoDescription: safeDesc,
|
|||
|
|
creatorName: authorName,
|
|||
|
|
creatorAvatar: authorAvatar,
|
|||
|
|
videoUrl: data.videoUrl || this.videoUrl,
|
|||
|
|
likeCount: likeCount,
|
|||
|
|
});
|
|||
|
|
console.log('页面数据更新完成,当前 articleData:', this.articleData);
|
|||
|
|
console.log('当前 isLoadingArticle:', this.isLoadingArticle);
|
|||
|
|
console.log('作者头像:', authorAvatar);
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error('文章详情获取失败:', error);
|
|||
|
|
this.setData({
|
|||
|
|
articleError: error.message || '获取文章详情失败',
|
|||
|
|
isLoadingArticle: false,
|
|||
|
|
});
|
|||
|
|
console.log('错误状态设置完成,articleError:', this.articleError);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '获取文章详情失败',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000,
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onBack() {
|
|||
|
|
uni.navigateBack();
|
|||
|
|
},
|
|||
|
|
// 下载视频
|
|||
|
|
onDownload() {
|
|||
|
|
if (!this.videoUrl) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '视频地址不存在',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uni.showLoading({
|
|||
|
|
title: '下载中...',
|
|||
|
|
mask: true
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 下载视频文件
|
|||
|
|
uni.downloadFile({
|
|||
|
|
url: this.videoUrl,
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.statusCode === 200) {
|
|||
|
|
// 保存到相册
|
|||
|
|
uni.saveVideoToPhotosAlbum({
|
|||
|
|
filePath: res.tempFilePath,
|
|||
|
|
success: () => {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '已保存到相册',
|
|||
|
|
icon: 'success',
|
|||
|
|
duration: 2000
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
fail: (error) => {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
console.error('保存到相册失败:', error);
|
|||
|
|
|
|||
|
|
// 如果是权限问题,提示用户开启权限
|
|||
|
|
if (error.errMsg.includes('auth')) {
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '需要相册权限',
|
|||
|
|
content: '请在设置中开启相册权限',
|
|||
|
|
confirmText: '去设置',
|
|||
|
|
success: (modalRes) => {
|
|||
|
|
if (modalRes.confirm) {
|
|||
|
|
uni.openSetting();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '保存失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '下载失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (error) => {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
console.error('下载失败:', error);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '下载失败,请重试',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
// 分享视频
|
|||
|
|
onShare() {
|
|||
|
|
uni.showActionSheet({
|
|||
|
|
itemList: ['分享到微信', '分享到朋友圈', '复制链接'],
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.tapIndex === 0) {
|
|||
|
|
// 分享到微信好友
|
|||
|
|
this.shareToWechat();
|
|||
|
|
} else if (res.tapIndex === 1) {
|
|||
|
|
// 分享到朋友圈
|
|||
|
|
this.shareToMoments();
|
|||
|
|
} else if (res.tapIndex === 2) {
|
|||
|
|
// 复制链接
|
|||
|
|
this.copyLink();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
// 分享到微信好友
|
|||
|
|
shareToWechat() {
|
|||
|
|
// #ifdef MP-WEIXIN
|
|||
|
|
// 小程序中使用按钮的 open-type="share"
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请使用右上角分享',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifdef H5
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请使用浏览器分享功能',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
// App中可以调用原生分享
|
|||
|
|
uni.share({
|
|||
|
|
provider: 'weixin',
|
|||
|
|
scene: 'WXSceneSession',
|
|||
|
|
type: 2,
|
|||
|
|
title: this.videoDescription || '精彩视频分享',
|
|||
|
|
summary: `来自 ${this.creatorName} 的视频`,
|
|||
|
|
href: this.videoUrl,
|
|||
|
|
imageUrl: this.articleData?.imageInput || '',
|
|||
|
|
success: () => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '分享成功',
|
|||
|
|
icon: 'success'
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('分享失败:', err);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '分享失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
// #endif
|
|||
|
|
},
|
|||
|
|
// 分享到朋友圈
|
|||
|
|
shareToMoments() {
|
|||
|
|
// #ifdef MP-WEIXIN
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请使用右上角分享到朋友圈',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifdef H5
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请使用浏览器分享功能',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
uni.share({
|
|||
|
|
provider: 'weixin',
|
|||
|
|
scene: 'WXSceneTimeline',
|
|||
|
|
type: 2,
|
|||
|
|
title: this.videoDescription || '精彩视频分享',
|
|||
|
|
summary: `来自 ${this.creatorName} 的视频`,
|
|||
|
|
href: this.videoUrl,
|
|||
|
|
imageUrl: this.articleData?.imageInput || '',
|
|||
|
|
success: () => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '分享成功',
|
|||
|
|
icon: 'success'
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('分享失败:', err);
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '分享失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
// #endif
|
|||
|
|
},
|
|||
|
|
// 复制链接
|
|||
|
|
copyLink() {
|
|||
|
|
const shareUrl = this.currentArticleId
|
|||
|
|
? `https://yourapp.com/pages/ai-generate/video?id=${this.currentArticleId}`
|
|||
|
|
: 'https://yourapp.com/pages/ai-generate/video';
|
|||
|
|
|
|||
|
|
uni.setClipboardData({
|
|||
|
|
data: shareUrl,
|
|||
|
|
success: () => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '链接已复制',
|
|||
|
|
icon: 'success'
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
fail: () => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '复制失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onVideoTap(e) {
|
|||
|
|
if (e && e.stopPropagation) {
|
|||
|
|
e.stopPropagation();
|
|||
|
|
}
|
|||
|
|
this.onPlayPause();
|
|||
|
|
},
|
|||
|
|
onVideoLongPress(e) {
|
|||
|
|
if (e && e.stopPropagation) {
|
|||
|
|
e.stopPropagation();
|
|||
|
|
}
|
|||
|
|
uni.showActionSheet({
|
|||
|
|
itemList: ['举报', '不感兴趣', '保存到相册'],
|
|||
|
|
success: res => {
|
|||
|
|
const actions = ['举报', '不感兴趣', '保存到相册'];
|
|||
|
|
uni.showToast({
|
|||
|
|
title: actions[res.tapIndex],
|
|||
|
|
icon: 'none',
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onPlayPause(e) {
|
|||
|
|
if (e && e.stopPropagation) {
|
|||
|
|
e.stopPropagation();
|
|||
|
|
}
|
|||
|
|
if (!this.videoContext || !this.isVideoReady) {
|
|||
|
|
console.warn('视频上下文未准备就绪');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (this.isPlaying) {
|
|||
|
|
this.safePause();
|
|||
|
|
} else {
|
|||
|
|
this.safePlay();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
safePlay() {
|
|||
|
|
if (!this.videoContext || !this.isVideoReady) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (this.isPlaying) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
this.videoContext.play();
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('播放失败:', error);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
safePause() {
|
|||
|
|
if (!this.videoContext || !this.isVideoReady) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!this.isPlaying) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
this.videoContext.pause();
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('暂停失败:', error);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
onVideoReady() {
|
|||
|
|
console.log('视频元数据加载完成');
|
|||
|
|
this.setData({
|
|||
|
|
isVideoReady: true,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onVideoPlay() {
|
|||
|
|
console.log('视频开始播放');
|
|||
|
|
this.setData({
|
|||
|
|
isPlaying: true,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onVideoPause() {
|
|||
|
|
console.log('视频暂停');
|
|||
|
|
this.setData({
|
|||
|
|
isPlaying: false,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onTimeUpdate(e) {
|
|||
|
|
const { currentTime, duration } = e.detail;
|
|||
|
|
const progress = (currentTime / duration) * 100;
|
|||
|
|
const minutes = Math.floor(currentTime / 60);
|
|||
|
|
const seconds = Math.floor(currentTime % 60);
|
|||
|
|
const timeStr = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|||
|
|
this.setData({
|
|||
|
|
currentTime: timeStr,
|
|||
|
|
progress: progress,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onVideoEnd() {
|
|||
|
|
this.setData({
|
|||
|
|
isPlaying: false,
|
|||
|
|
progress: 0,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onCreatorTap() {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: `查看${this.creatorName}的主页`,
|
|||
|
|
icon: 'none',
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onFollow() {
|
|||
|
|
const isFollowing = !this.isFollowing;
|
|||
|
|
this.setData({
|
|||
|
|
isFollowing: isFollowing,
|
|||
|
|
});
|
|||
|
|
uni.showToast({
|
|||
|
|
title: isFollowing ? '关注成功' : '取消关注',
|
|||
|
|
icon: 'success',
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onLike() {
|
|||
|
|
const isLiked = !this.isLiked;
|
|||
|
|
const likeCount = isLiked ? this.likeCount + 1 : this.likeCount - 1;
|
|||
|
|
this.setData({
|
|||
|
|
isLiked: isLiked,
|
|||
|
|
likeCount: likeCount,
|
|||
|
|
});
|
|||
|
|
if (isLiked) {
|
|||
|
|
uni.vibrateShort();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
onCreateSimilar() {
|
|||
|
|
const description = this.videoDescription;
|
|||
|
|
const encodedDescription = encodeURIComponent(description);
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: `/pages/ai-generate/oneclick?description=${encodedDescription}&from=video`,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onConsult() {
|
|||
|
|
const url = this.chatUrl;
|
|||
|
|
if (!url) {
|
|||
|
|
uni.showToast({ title: '暂无客服链接', icon: 'none' });
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
// 统一跳转到内置网页容器
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: `/pages/users/web_page/index?webUel=${encodeURIComponent(url)}&title=客服`
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onViewHistory() {
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: '/pages/ai-generate/assets',
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onTouchStart(e) {
|
|||
|
|
if (!this.isSwipeEnabled || this.isLoadingArticle) return;
|
|||
|
|
this.setData({
|
|||
|
|
touchStartY: e.touches[0].clientY,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onTouchEnd(e) {
|
|||
|
|
if (!this.isSwipeEnabled || this.isLoadingArticle) return;
|
|||
|
|
const touchEndY = e.changedTouches[0].clientY;
|
|||
|
|
const deltaY = touchEndY - this.touchStartY;
|
|||
|
|
const minSwipeDistance = 50;
|
|||
|
|
this.setData({
|
|||
|
|
touchEndY: touchEndY,
|
|||
|
|
});
|
|||
|
|
if (Math.abs(deltaY) > minSwipeDistance) {
|
|||
|
|
if (deltaY > 0) {
|
|||
|
|
this.loadPreviousArticle();
|
|||
|
|
} else {
|
|||
|
|
this.loadNextArticle();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
loadPreviousArticle() {
|
|||
|
|
const currentId = parseInt(this.currentArticleId);
|
|||
|
|
if (currentId && currentId > 1) {
|
|||
|
|
const previousId = currentId - 1;
|
|||
|
|
console.log('加载上一篇文章,ID:', previousId);
|
|||
|
|
this.loadArticleDetail(previousId);
|
|||
|
|
this.setData({
|
|||
|
|
currentArticleId: previousId.toString(),
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '已经是第一篇了',
|
|||
|
|
icon: 'none',
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
loadNextArticle() {
|
|||
|
|
const currentId = parseInt(this.currentArticleId);
|
|||
|
|
if (currentId) {
|
|||
|
|
const nextId = currentId + 1;
|
|||
|
|
console.log('加载下一篇文章,ID:', nextId);
|
|||
|
|
this.loadArticleDetail(nextId);
|
|||
|
|
this.setData({
|
|||
|
|
currentArticleId: nextId.toString(),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
onToggleDescription() {
|
|||
|
|
this.setData({
|
|||
|
|
isDescriptionExpanded: !this.isDescriptionExpanded,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
onShareAppMessage() {
|
|||
|
|
try {
|
|||
|
|
// 获取分享标题,优先使用articleData.title
|
|||
|
|
let shareTitle = '精彩视频分享'; // 默认标题
|
|||
|
|
if (this.articleData && this.articleData.title) {
|
|||
|
|
shareTitle = this.articleData.title;
|
|||
|
|
// 限制标题长度,微信建议不超过28个字符
|
|||
|
|
if (shareTitle.length > 28) {
|
|||
|
|
shareTitle = shareTitle.substring(0, 25) + '...';
|
|||
|
|
}
|
|||
|
|
} else if (this.creatorName) {
|
|||
|
|
shareTitle = `${this.creatorName}的作品`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取分享缩略图,优先使用articleData.imageInput
|
|||
|
|
let shareImageUrl = '/static/images/video-share.png'; // 默认缩略图
|
|||
|
|
if (this.articleData && this.articleData.imageInput) {
|
|||
|
|
shareImageUrl = this.articleData.imageInput;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建分享路径,包含当前文章ID
|
|||
|
|
const sharePath = this.currentArticleId
|
|||
|
|
? `/pages/ai-generate/video?id=${this.currentArticleId}`
|
|||
|
|
: '/pages/ai-generate/assets';
|
|||
|
|
|
|||
|
|
console.log('分享配置:', {
|
|||
|
|
title: shareTitle,
|
|||
|
|
path: sharePath,
|
|||
|
|
imageUrl: shareImageUrl
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
title: shareTitle,
|
|||
|
|
path: sharePath,
|
|||
|
|
imageUrl: shareImageUrl,
|
|||
|
|
};
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('分享配置失败:', error);
|
|||
|
|
// 发生错误时返回默认配置
|
|||
|
|
return {
|
|||
|
|
title: '精彩视频分享',
|
|||
|
|
path: '/pages/ai-generate/video',
|
|||
|
|
imageUrl: '/static/images/video-share.png',
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
onShareTimeline() {
|
|||
|
|
try {
|
|||
|
|
// 获取分享标题,优先使用articleData.title
|
|||
|
|
let shareTitle = '精彩视频分享'; // 默认标题
|
|||
|
|
if (this.articleData && this.articleData.title) {
|
|||
|
|
shareTitle = this.articleData.title;
|
|||
|
|
// 朋友圈分享标题建议更简洁,限制在20个字符内
|
|||
|
|
if (shareTitle.length > 20) {
|
|||
|
|
shareTitle = shareTitle.substring(0, 17) + '...';
|
|||
|
|
}
|
|||
|
|
} else if (this.creatorName) {
|
|||
|
|
shareTitle = `${this.creatorName}的作品`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取分享缩略图,优先使用articleData.imageInput
|
|||
|
|
let shareImageUrl = '/static/images/video-share.png'; // 默认缩略图
|
|||
|
|
if (this.articleData && this.articleData.imageInput) {
|
|||
|
|
shareImageUrl = this.articleData.imageInput;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('朋友圈分享配置:', {
|
|||
|
|
title: shareTitle,
|
|||
|
|
imageUrl: shareImageUrl
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
title: shareTitle,
|
|||
|
|
imageUrl: shareImageUrl,
|
|||
|
|
};
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('朋友圈分享配置失败:', error);
|
|||
|
|
// 发生错误时返回默认配置
|
|||
|
|
return {
|
|||
|
|
title: '精彩视频分享',
|
|||
|
|
imageUrl: '/static/images/video-share.png',
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
onPullDownRefresh() {
|
|||
|
|
this.loadVideoData();
|
|||
|
|
setTimeout(() => {
|
|||
|
|
uni.stopPullDownRefresh();
|
|||
|
|
}, 1000);
|
|||
|
|
},
|
|||
|
|
setData(data) {
|
|||
|
|
let that = this;
|
|||
|
|
Object.keys(data).forEach(key => {
|
|||
|
|
that[key] = data[key];
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style>
|
|||
|
|
/* 视频播放页面样式 */
|
|||
|
|
.video-container {
|
|||
|
|
width: 100vw;
|
|||
|
|
height: 100vh;
|
|||
|
|
background: #000000; margin-top: 80rpx;
|
|||
|
|
position: relative;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* AI生成内容标识 */
|
|||
|
|
.ai-notice {
|
|||
|
|
position: fixed;
|
|||
|
|
right: 12px;width: 100px;
|
|||
|
|
height: 30px; top: 92px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
gap: 8rpx;
|
|||
|
|
padding: 12rpx 24rpx;
|
|||
|
|
background: rgba(0, 0, 0, 0.3);
|
|||
|
|
border: 1rpx solid rgba(66, 202, 77, 0.5);
|
|||
|
|
border-radius: 40rpx;
|
|||
|
|
backdrop-filter: blur(10rpx);
|
|||
|
|
z-index: 100;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.ai-notice-icon {
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.ai-notice-text {
|
|||
|
|
font-size: 20rpx;
|
|||
|
|
color: #42ca4d;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.video-player {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
position: relative;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 顶部控制栏 */
|
|||
|
|
.top-controls {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
height: 48px;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: flex-end;
|
|||
|
|
padding: 0 16px 16px;
|
|||
|
|
background: linear-gradient(180deg, rgba(0,0,0,0.6) 0%, transparent 100%);
|
|||
|
|
z-index: 10;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.left-controls {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.back-btn {
|
|||
|
|
width: 32px;
|
|||
|
|
height: 32px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
margin-right: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-back {
|
|||
|
|
font-size: 24px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 文章详情样式 */
|
|||
|
|
.article-status {
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
padding: 12px 16px;
|
|||
|
|
background: rgba(0, 0, 0, 0.6);
|
|||
|
|
border-radius: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.loading-indicator {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.loading-text {
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-size: 14px;
|
|||
|
|
opacity: 0.8;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.error-message {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.error-text {
|
|||
|
|
color: #ff6b6b;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-detail {
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
padding: 16px;
|
|||
|
|
background: rgba(0, 0, 0, 0.6);
|
|||
|
|
border-radius: 12px;
|
|||
|
|
backdrop-filter: blur(10px);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-header {
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-title {
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-meta {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.publish-time {
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-size: 12px;
|
|||
|
|
opacity: 0.7;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-category {
|
|||
|
|
color: #4CAF50;
|
|||
|
|
font-size: 12px;
|
|||
|
|
background: rgba(76, 175, 80, 0.2);
|
|||
|
|
padding: 2px 8px;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-content {
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.content-text {
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-size: 14px;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
opacity: 0.9;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.article-tags {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
gap: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tag-item {
|
|||
|
|
color: #2196F3;
|
|||
|
|
font-size: 12px;
|
|||
|
|
background: rgba(33, 150, 243, 0.2);
|
|||
|
|
padding: 4px 8px;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-display {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.right-controls {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.signal-icons {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-right: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.signal, .wifi, .battery {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
margin-left: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.share-btn {
|
|||
|
|
width: 32px;
|
|||
|
|
height: 32px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-share {
|
|||
|
|
font-size: 18px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 视频内容区域 */
|
|||
|
|
.video-content {
|
|||
|
|
flex: 1;
|
|||
|
|
position: relative;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.video-element {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
object-fit: cover;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.play-indicator {
|
|||
|
|
position: absolute;
|
|||
|
|
width: 80px;
|
|||
|
|
height: 80px;
|
|||
|
|
background: rgba(0, 0, 0, 0.6);
|
|||
|
|
border-radius: 40px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
transition: opacity 0.3s ease;
|
|||
|
|
backdrop-filter: blur(10px);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.play-indicator.hide {
|
|||
|
|
opacity: 0;
|
|||
|
|
pointer-events: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.play-indicator.show {
|
|||
|
|
opacity: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.play-icon {
|
|||
|
|
font-size: 32px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
margin-left: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 底部信息区域 */
|
|||
|
|
.bottom-info {
|
|||
|
|
position: absolute;
|
|||
|
|
bottom: 60rpx;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
padding: 11px;
|
|||
|
|
background: linear-gradient(0deg, rgba(0,0,0,0.8) 0%, transparent 100%);
|
|||
|
|
z-index: 10;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 创作者信息 */
|
|||
|
|
.creator-info {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.creator-avatar {
|
|||
|
|
width: 40px;
|
|||
|
|
height: 40px;
|
|||
|
|
border-radius: 20px;
|
|||
|
|
margin-right: 12px;
|
|||
|
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.creator-details {
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.creator-name {
|
|||
|
|
font-size: 16px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.follow-btn {
|
|||
|
|
padding: 6px 16px;
|
|||
|
|
background: #ffffff;
|
|||
|
|
color: #333333;
|
|||
|
|
border-radius: 16px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
transition: all 0.3s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.follow-btn.following {
|
|||
|
|
background: rgba(255, 255, 255, 0.3);
|
|||
|
|
color: #ffffff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 视频描述信息 */
|
|||
|
|
.video-info {
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-tags {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 8px;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tag {
|
|||
|
|
padding: 4px 8px;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
font-size: 12px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tag-info {
|
|||
|
|
background: rgba(79, 172, 254, 0.8);
|
|||
|
|
color: #ffffff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tag-ai {
|
|||
|
|
background: rgba(118, 75, 162, 0.8);
|
|||
|
|
color: #ffffff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.video-description {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
opacity: 0.9;
|
|||
|
|
display: -webkit-box;
|
|||
|
|
-webkit-box-orient: vertical;
|
|||
|
|
-webkit-line-clamp: 2;
|
|||
|
|
line-clamp: 2;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
word-break: break-all;
|
|||
|
|
cursor: pointer;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.video-description.expanded {
|
|||
|
|
-webkit-line-clamp: unset;
|
|||
|
|
line-clamp: unset;
|
|||
|
|
overflow: visible;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 展开/收起切换按钮 */
|
|||
|
|
.expand-toggle {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-top: 8px;
|
|||
|
|
padding: 4px 0;
|
|||
|
|
cursor: pointer;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-toggle .iconfont {
|
|||
|
|
font-size: 16px;
|
|||
|
|
color: rgba(255, 255, 255, 0.7);
|
|||
|
|
transition: all 0.3s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-toggle:active .iconfont {
|
|||
|
|
color: rgba(255, 255, 255, 1);
|
|||
|
|
transform: scale(1.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 互动操作区 */
|
|||
|
|
.interaction-area {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.like-section {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.like-btn {
|
|||
|
|
width: 44px;
|
|||
|
|
height: 44px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
margin-right: 8px;
|
|||
|
|
transition: transform 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.like-btn:active {
|
|||
|
|
transform: scale(1.2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.heart-icon {
|
|||
|
|
font-size: 24px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.like-count {
|
|||
|
|
font-size: 16px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-buttons {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 悬浮操作按钮 */
|
|||
|
|
.floating-actions {
|
|||
|
|
position: fixed;
|
|||
|
|
right: 16px;
|
|||
|
|
bottom: 35%;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 20px;
|
|||
|
|
z-index: 100;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.floating-btn {
|
|||
|
|
width: 42px;
|
|||
|
|
height: 42px;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
gap: 4px;
|
|||
|
|
background: linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.25) 100%);
|
|||
|
|
border: 2px solid rgba(255, 255, 255, 0.15);
|
|||
|
|
border-radius: 50%;
|
|||
|
|
backdrop-filter: blur(20px);
|
|||
|
|
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
|||
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4),
|
|||
|
|
0 4px 8px rgba(0, 0, 0, 0.2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.floating-btn:active {
|
|||
|
|
transform: scale(0.92);
|
|||
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3),
|
|||
|
|
0 2px 4px rgba(0, 0, 0, 0.2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 下载按钮 */
|
|||
|
|
.download-btn {
|
|||
|
|
background: linear-gradient(135deg, rgba(76, 175, 80, 0.2) 0%, rgba(56, 142, 60, 0.4) 100%);
|
|||
|
|
border-color: rgba(139, 195, 74, 0.3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.download-btn:active {
|
|||
|
|
background: linear-gradient(135deg, rgba(76, 175, 80, 1) 0%, rgba(56, 142, 60, 0.9) 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 分享按钮 */
|
|||
|
|
.share-btn {
|
|||
|
|
background: linear-gradient(135deg, rgba(33, 150, 243, 0.2) 0%, rgba(25, 118, 210, 0.4) 100%);
|
|||
|
|
border-color: rgba(100, 181, 246, 0.3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.share-btn:active {
|
|||
|
|
background: linear-gradient(135deg, rgba(33, 150, 243, 1) 0%, rgba(25, 118, 210, 0.9) 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* CSS绘制的下载图标 */
|
|||
|
|
.icon-download {
|
|||
|
|
width: 20px;
|
|||
|
|
height: 20px;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-download::before {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
left: 50%;
|
|||
|
|
top: 0;
|
|||
|
|
width: 3px;
|
|||
|
|
height: 14px;
|
|||
|
|
background: #ffffff;
|
|||
|
|
transform: translateX(-50%);
|
|||
|
|
border-radius: 2px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-download::after {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
left: 50%;
|
|||
|
|
bottom: 0;
|
|||
|
|
width: 0;
|
|||
|
|
height: 0;
|
|||
|
|
border-left: 5px solid transparent;
|
|||
|
|
border-right: 5px solid transparent;
|
|||
|
|
border-top: 6px solid #ffffff;
|
|||
|
|
transform: translateX(-50%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* CSS绘制的分享图标 */
|
|||
|
|
.icon-share {
|
|||
|
|
width: 20px;
|
|||
|
|
height: 20px;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-share::before {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
left: 50%;
|
|||
|
|
bottom: 0;
|
|||
|
|
width: 3px;
|
|||
|
|
height: 14px;
|
|||
|
|
background: #ffffff;
|
|||
|
|
transform: translateX(-50%);
|
|||
|
|
border-radius: 2px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-share::after {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
left: 50%;
|
|||
|
|
top: 0;
|
|||
|
|
width: 0;
|
|||
|
|
height: 0;
|
|||
|
|
border-left: 5px solid transparent;
|
|||
|
|
border-right: 5px solid transparent;
|
|||
|
|
border-bottom: 6px solid #ffffff;
|
|||
|
|
transform: translateX(-50%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.floating-label {
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-weight: 500;
|
|||
|
|
letter-spacing: 0.3px;
|
|||
|
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.consult-btn {
|
|||
|
|
padding: 12px 24px;
|
|||
|
|
background: rgba(255, 255, 255, 0.15);
|
|||
|
|
color: #ffffff;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.5);
|
|||
|
|
border-radius: 24px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
transition: transform 0.2s ease, background 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.consult-btn:active {
|
|||
|
|
transform: scale(0.95);
|
|||
|
|
background: rgba(255, 255, 255, 0.25);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn {
|
|||
|
|
padding: 12px 24px;
|
|||
|
|
background: #ffffff;
|
|||
|
|
color: #333333;
|
|||
|
|
border-radius: 24px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
transition: transform 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn:active {
|
|||
|
|
transform: scale(0.95);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 进度条 */
|
|||
|
|
.progress-bar {
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-track {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 2px;
|
|||
|
|
background: rgba(255, 255, 255, 0.3);
|
|||
|
|
border-radius: 1px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-fill {
|
|||
|
|
height: 100%;
|
|||
|
|
background: #ffffff;
|
|||
|
|
border-radius: 1px;
|
|||
|
|
transition: width 0.1s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 点赞动画 */
|
|||
|
|
@keyframes likeAnimation {
|
|||
|
|
0% {
|
|||
|
|
transform: scale(1);
|
|||
|
|
}
|
|||
|
|
50% {
|
|||
|
|
transform: scale(1.3);
|
|||
|
|
}
|
|||
|
|
100% {
|
|||
|
|
transform: scale(1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.like-btn.liked .heart-icon {
|
|||
|
|
animation: likeAnimation 0.6s ease;
|
|||
|
|
}
|
|||
|
|
</style>
|