1305 lines
33 KiB
Vue
1305 lines
33 KiB
Vue
<template>
|
||
<view class="navbox">
|
||
<view class="status_bar"></view>
|
||
<uni-nav-bar
|
||
left-icon="left"
|
||
title="视频详情"
|
||
@clickLeft="goBack"
|
||
color="#8B2316"
|
||
:border="false"
|
||
backgroundColor="#eeeeee"
|
||
>
|
||
<template #right>
|
||
<view class="nav-actions" v-if="from != 'download'">
|
||
<view class="collect-img" @click="shareToggle">
|
||
<image class="share-img-icon" :src="shareIcon" mode="aspectFill" />
|
||
</view>
|
||
<view class="collect-img" @click="toCollection">
|
||
<image
|
||
class="collect-img-icon"
|
||
:src="videoInfo.isCollection ? collectImg : discollectImg"
|
||
mode="aspectFill"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</uni-nav-bar>
|
||
</view>
|
||
|
||
<!-- <video
|
||
v-if="showVideo"
|
||
class="player-wrapper"
|
||
:style="{width: videoWidth + 'px'}"
|
||
:src="videoSrc"
|
||
controls
|
||
object-fit="contain"
|
||
:autoplay="false"
|
||
></video> -->
|
||
<sunny-video
|
||
v-if="showVideo"
|
||
class="player-wrapper"
|
||
:src="videoSrc"
|
||
:videoHeight="220"
|
||
:seekTime="0"
|
||
@fullscreenchange="onFullscreenChange"
|
||
/>
|
||
<!-- 标签切换 -->
|
||
<cover-view class="tabs" v-if="from != 'download'" :style="{ opacity: isFullScreen ? 0: 1 }">
|
||
<cover-view
|
||
class="tab"
|
||
:class="{ active: activeTab === 'info' }"
|
||
@click="switchTab('info')"
|
||
>
|
||
视频简介
|
||
<cover-view class="tab-line" v-if="activeTab === 'info'"></cover-view>
|
||
</cover-view>
|
||
<cover-view
|
||
class="tab"
|
||
:class="{ active: activeTab === 'comment' }"
|
||
@click="switchTab('comment')"
|
||
>
|
||
评论
|
||
<cover-view class="tab-line" v-if="activeTab === 'comment'"></cover-view>
|
||
</cover-view>
|
||
</cover-view>
|
||
<view class="video-detail-page" v-if="from != 'download'">
|
||
<!-- <scroll-view
|
||
class="content-scroll"
|
||
scroll-y
|
||
:show-scrollbar="false"
|
||
@scrolltolower="onScrollToLower"
|
||
lower-threshold="60"
|
||
> -->
|
||
<view class="content-scroll">
|
||
<!-- 内容区 -->
|
||
<view v-if="activeTab === 'info'" class="intro">
|
||
<!-- 显示传递过来的视频信息 -->
|
||
<!-- <view v-if="pageParams.title" class="video-info">
|
||
<view class="video-title">{{
|
||
decodeURIComponent(pageParams.title)
|
||
}}</view>
|
||
<view v-if="pageParams.author" class="video-author">{{
|
||
decodeURIComponent(pageParams.author)
|
||
}}</view>
|
||
</view> -->
|
||
<!-- <view class="speaker">{{ videoInfo.public_name }}</view> -->
|
||
<text class="intro-text">{{ videoInfo.note }}</text>
|
||
</view>
|
||
<view v-else class="comments">
|
||
<view v-if="commentList.length === 0" class="empty">暂无评论</view>
|
||
<view v-else>
|
||
<view class="comment-item" v-for="(c, idx) in commentList" :key="idx">
|
||
<image class="avatar" :src="c.avatar" mode="aspectFill" />
|
||
<view class="meta">
|
||
<view class="name">{{ c.name }}</view>
|
||
<view class="content">{{ c.content }}</view>
|
||
<view class="time">{{ c.time }}</view>
|
||
<view v-if="c.children && c.children.length" class="child-list">
|
||
<view class="child-item" v-for="(r, i) in c.children" :key="i">
|
||
<image
|
||
class="avatar small"
|
||
:src="r.avatar"
|
||
mode="aspectFill"
|
||
/>
|
||
<view class="meta">
|
||
<view class="name">{{ r.name }}</view>
|
||
<view class="content">{{ r.content }}</view>
|
||
<view class="time">{{ r.time }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="reply-btn" @click="onReply(c)">回复</view>
|
||
</view>
|
||
<!-- 加载状态/没有更多 -->
|
||
<view v-if="loading" class="list-loading">加载中...</view>
|
||
<view v-if="noMore" class="list-no-more">没有更多了</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 留白,避免被底部按钮遮挡 -->
|
||
<!-- <view class="bottom-spacer"></view> -->
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部区域:信息页为下载条,评论页为上传图片+输入+发送 -->
|
||
<view v-if="activeTab === 'info' && from != 'download'" class="bottom-download" @click="onDownload">
|
||
<text class="download-text" v-if="!hasDownload"
|
||
>点击下载<text v-if="!isVideoDownloadRecord && welfareNum <= 0"
|
||
>(限时<text class="discount">5</text>折,仅需{{
|
||
videoInfo.point
|
||
}}积分)</text
|
||
>
|
||
<text v-if="!isVideoDownloadRecord && welfareNum > 0">(剩余免费下载{{ welfareNum }}次数)</text>
|
||
</text
|
||
>
|
||
|
||
<text class="download-text" v-else-if="downLoadStatus === 'loading' || downLoadStatus === 'failed'">视频缓存中</text>
|
||
<text class="download-text" v-else-if="downLoadStatus === 'completed'">查看缓存</text>
|
||
</view>
|
||
<view v-if="activeTab !== 'info' && from != 'download'" class="bottom-comment">
|
||
<input
|
||
class="comment-input"
|
||
v-model="commentText"
|
||
placeholder="我也说一句"
|
||
confirm-type="send"
|
||
@confirm="sendComment"
|
||
/>
|
||
<view class="send-btn" @click="sendComment">发送</view>
|
||
</view>
|
||
<unidialog
|
||
:visible="networkVisible"
|
||
:content="networkContent"
|
||
@close="networkVisible = false"
|
||
@confirm="networkConfirm"
|
||
></unidialog>
|
||
<unidialog
|
||
:visible="pointVisible"
|
||
:content="pointContent"
|
||
@close="pointVisible = false"
|
||
@confirm="pointConfirm"
|
||
></unidialog>
|
||
<unidialog
|
||
:visible="notEnoughVisible"
|
||
:content="notEnoughContent"
|
||
@close="notEnoughVisible = false"
|
||
@confirm="notEnoughConfirm"
|
||
></unidialog>
|
||
<!-- 分享弹窗 -->
|
||
<uni-popup ref="shareRef" type="bottom" safeArea backgroundColor="#fff">
|
||
<view class="share-popup">
|
||
<view class="share-title">分享到</view>
|
||
<view class="share-content">
|
||
<view class="share-item" @click="shareToWechat">
|
||
<view class="share-icon wechat-icon">
|
||
<image class="share-img" :src="wxImg" mode="aspectFill" />
|
||
</view>
|
||
<text class="share-text">微信</text>
|
||
</view>
|
||
<view class="share-item" @click="shareToMoments">
|
||
<view class="share-icon moments-icon">
|
||
<image class="share-img" :src="friendImg" mode="aspectFill" />
|
||
</view>
|
||
<text class="share-text">朋友圈</text>
|
||
</view>
|
||
<view class="share-item" @click="shareToWeibo">
|
||
<view class="share-icon weibo-icon">
|
||
<image class="share-img" :src="sinaImg" mode="aspectFill" />
|
||
</view>
|
||
<text class="share-text">新浪微博</text>
|
||
</view>
|
||
</view>
|
||
<view class="share-cancel" @click="closeShare">
|
||
<text>取消</text>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, nextTick } from "vue";
|
||
import uniVideo from "@/components/uniVideo/uniVideo.vue";
|
||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||
import unidialog from "@/components/dialog/dialog.vue";
|
||
import collectImg from "@/static/icon_book_collect_sel.png";
|
||
import discollectImg from "@/static/icon_book_collect_nor.png";
|
||
import shareIcon from "@/static/icon_share.png";
|
||
import sinaImg from "@/static/share_sina.png";
|
||
import wxImg from "@/static/share_weixin.png";
|
||
import friendImg from "@/static/share_wxc.png";
|
||
import logoImg from "@/static/weiboShare.png";
|
||
import api from "@/api/api";
|
||
import docUrl from "@/utils/docUrl";
|
||
import navTo from "@/utils/navTo";
|
||
const shareLink = ref("");
|
||
import otherHost from "@/utils/otherHost";
|
||
const video_uuid = ref("");
|
||
const videoInfo = ref({});
|
||
const networkVisible = ref(false);
|
||
const networkContent = ref("");
|
||
const pointVisible = ref(false);
|
||
const pointContent = ref("");
|
||
const notEnoughVisible = ref(false);
|
||
const notEnoughContent = ref("");
|
||
const welfareNum = ref(0);
|
||
const showVideo = ref(false);
|
||
const videoWidth = ref(375);
|
||
const hasDownload = ref(false);
|
||
const downLoadStatus = ref('start');
|
||
let downList = uni.getStorageSync("downLoadVideo") || [];
|
||
const downLoadList = ref(downList);
|
||
const isFullScreen = ref(false);
|
||
//import DomVideoPlayer from 'uniapp-video-player'
|
||
import sunnyVideo from "@/uni_modules/sunny-video/components/sunny-video/sunny-video.vue";
|
||
import downloadStore from "@/store/downloadStoreVideo.js";
|
||
const downloadTasks = ref([]);
|
||
// 添加下载任务
|
||
const addDownloadTask = (item) => {
|
||
// 使用store添加任务
|
||
const taskIndex = downloadStore.addTask(item);
|
||
// 同步任务列表
|
||
syncTasksFromStore();
|
||
// 开始下载
|
||
startDownload(taskIndex);
|
||
};
|
||
const onFullscreenChange = (e) => {
|
||
let { fullScreen, direction } = e;
|
||
nextTick(() => {
|
||
isFullScreen.value = fullScreen;
|
||
});
|
||
};
|
||
// 开始下载
|
||
const startDownload = (index) => {
|
||
const taskItem = downloadStore.getTask(index);
|
||
if (!taskItem) return;
|
||
hasDownload.value = true;
|
||
downLoadStatus.value = 'loading';
|
||
const task = uni.downloadFile({
|
||
url: taskItem.url,
|
||
success: (res1) => {
|
||
//console.log("res1:"+JSON.stringify(res1));
|
||
if (res1.statusCode === 200) {
|
||
downloadStore.updateTask(index, {
|
||
status: "completed",
|
||
filePath: res1.tempFilePath,
|
||
});
|
||
downLoadStatus.value = 'completed';
|
||
uni.showToast({
|
||
title: "下载成功",
|
||
icon: "none",
|
||
});
|
||
downLoadStatus.value = 'completed';
|
||
|
||
uni.saveFile({
|
||
tempFilePath: res1.tempFilePath,
|
||
success: function (res2) {
|
||
console.log("res2:"+JSON.stringify(res2));
|
||
uni.getSavedFileInfo({
|
||
filePath: res2.savedFilePath,
|
||
success: function (res) {
|
||
|
||
console.log("res:"+JSON.stringify(res));
|
||
console.log("size:"+res.size);
|
||
downloadStore.updateTask(index, {
|
||
status: "completed",
|
||
localPath: res2.savedFilePath,
|
||
size: res.size,
|
||
});
|
||
VideoDownloadRecord();
|
||
},
|
||
});
|
||
},
|
||
});
|
||
} else {
|
||
downloadStore.updateTask(index, {
|
||
status: "failed",
|
||
});
|
||
uni.showToast({
|
||
title: "下载失败",
|
||
icon: "none",
|
||
});
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
downloadStore.updateTask(index, {
|
||
status: "failed",
|
||
});
|
||
uni.showToast({
|
||
title: "下载失败: " + (err.errMsg || "未知错误"),
|
||
icon: "none",
|
||
duration: 2000,
|
||
});
|
||
},
|
||
});
|
||
|
||
// 监听下载进度
|
||
task.onProgressUpdate((update) => {
|
||
const currentTask = downloadStore.getTask(index);
|
||
if (currentTask && currentTask.status === "downloading") {
|
||
downloadStore.updateTask(index, {
|
||
progress: update.progress,
|
||
downloadSize: update.totalBytesWritten,
|
||
totalSize: update.totalBytesExpectedToWrite,
|
||
});
|
||
}
|
||
});
|
||
|
||
// 保存task对象到store(用于暂停/继续)
|
||
downloadStore.updateTask(index, {
|
||
task: task,
|
||
});
|
||
};
|
||
|
||
const syncTasksFromStore = () => {
|
||
downloadTasks.value = downloadStore.getTasks();
|
||
};
|
||
|
||
const notEnoughConfirm = () => {
|
||
notEnoughVisible.value = false;
|
||
navTo({
|
||
url: "/pages_app/buyPoint/buyPoint",
|
||
});
|
||
};
|
||
const pointConfirm = () => {
|
||
pointVisible.value = false;
|
||
payVideoDownload();
|
||
};
|
||
const toCollection = () => {
|
||
if (videoInfo.value.isCollection == 1) {
|
||
discollection();
|
||
} else {
|
||
collection();
|
||
}
|
||
};
|
||
const networkConfirm = () => {
|
||
networkVisible.value = false;
|
||
|
||
if(welfareNum.value > 0) {
|
||
useWelfareNum();
|
||
}else{
|
||
pointVisible.value = true;
|
||
}
|
||
|
||
};
|
||
const addVideoWatchRecord = async () => {
|
||
const res = await api.addVideoWatchRecord({
|
||
video_uuid: video_uuid.value,
|
||
});
|
||
if (res.code == 200) {
|
||
}
|
||
};
|
||
const onLoadedmetadata = (e) => {
|
||
un.showModal({
|
||
content: "加载完成:" + JSON.stringify(e),
|
||
showCancel: false,
|
||
});
|
||
};
|
||
const onVideoError = (e) => {
|
||
uni.showModal({
|
||
content: JSON.stringify(e),
|
||
showCancel: false,
|
||
});
|
||
};
|
||
// 接收页面参数
|
||
const pageParams = ref({});
|
||
const useWelfareNum = async () => {
|
||
const res = await api.useWelfareNum({
|
||
type: 1,
|
||
other_uuid:video_uuid.value,
|
||
});
|
||
if (res.code == 1) {
|
||
uni.showToast({ title: "使用次数成功", icon: "none" });
|
||
welfareNum.value--;
|
||
addDownloadTask({
|
||
url: videoSrc.value,
|
||
id: video_uuid.value,
|
||
imgpath: videoInfo.value.imgpath,
|
||
author: videoInfo.value.public_name,
|
||
name: videoInfo.value.name,
|
||
});
|
||
}
|
||
};
|
||
const videoDetail = async () => {
|
||
const res = await api.videoDetail({ video_uuid: video_uuid.value });
|
||
if (res.code == 200) {
|
||
const userInfo = uni.getStorageSync("userInfo");
|
||
videoInfo.value = res.video;
|
||
|
||
//hasDownload.value = downLoadList.value.includes(video_uuid.value);
|
||
let vid = res.video.polyv_uuid;
|
||
let uuid = vid.substring(0, 10);
|
||
let index = vid.lastIndexOf("_");
|
||
let f = vid.substring(index - 1, index);
|
||
let id = vid.substring(0, index + 1);
|
||
//videoSrc.value = 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4';
|
||
videoSrc.value = `http://mpv.videocc.net/${uuid}/${f}/${id}1.mp4`;
|
||
showVideo.value = true;
|
||
shareLink.value =
|
||
otherHost +
|
||
"/video/hcp_detial?share=1&uuid=" +
|
||
video_uuid.value +
|
||
"&expertshare=videoshare&fromtype=doctor";
|
||
}
|
||
};
|
||
const collection = async () => {
|
||
const res = await api.collection({
|
||
other_uuid: video_uuid.value,
|
||
type: 5,
|
||
});
|
||
if (res.code == 200) {
|
||
uni.showToast({ title: "收藏成功", icon: "none" });
|
||
videoDetail();
|
||
}
|
||
};
|
||
const discollection = async () => {
|
||
const res = await api.discollection({
|
||
other_uuid: video_uuid.value,
|
||
type: 5,
|
||
});
|
||
if (res.code == 200) {
|
||
uni.showToast({ title: "取消收藏成功", icon: "none" });
|
||
videoDetail();
|
||
}
|
||
};
|
||
const isVideoDownloadRecord = ref(false);
|
||
const VideoDownloadRecord = async () => {
|
||
const res = await api.isVideoDownloadRecord({ video_uuid: video_uuid.value });
|
||
if (res.code == 200) {
|
||
isVideoDownloadRecord.value = res.result == 0 ? false : true;
|
||
if(isVideoDownloadRecord.value) {
|
||
downloadTasks.value.forEach(item => {
|
||
if (item.id == video_uuid.value) {
|
||
uni.getSavedFileInfo({
|
||
filePath: item.localPath, //仅做示例用,非真正的文件路径
|
||
success: function (res) {
|
||
hasDownload.value = true;
|
||
downLoadStatus.value = 'completed';
|
||
},
|
||
fail: function (err) {
|
||
// hasDownload.value = false;
|
||
// downLoadStatus.value = 'failed';
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
}
|
||
}
|
||
};
|
||
|
||
const getWelfareNum = async () => {
|
||
const res = await api.getWelfareNum({
|
||
type: 1,
|
||
});
|
||
if (res.code == 1) {
|
||
welfareNum.value = res.WelfareNum;
|
||
}
|
||
};
|
||
|
||
const videoCommentListV2 = async () => {
|
||
loading.value = true;
|
||
try {
|
||
const res = await api.videoCommentListV2({
|
||
uuid: video_uuid.value,
|
||
});
|
||
if (res && res.code == 200 && Array.isArray(res.data)) {
|
||
const mapped = res.data.map(mapComment);
|
||
commentList.value = mapped.reverse();
|
||
noMore.value = true;
|
||
} else {
|
||
noMore.value = true;
|
||
}
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
// 恢复正在下载的任务
|
||
const resumeDownloadingTasks = () => {
|
||
// 使用 nextTick 确保在页面渲染后再恢复下载任务
|
||
nextTick(() => {
|
||
downloadStore.resumeDownloadingTasks((index) => {
|
||
// 重新开始下载(uni.downloadFile不支持断点续传,所以从0开始)
|
||
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
|
||
startDownload(index);
|
||
});
|
||
});
|
||
};
|
||
|
||
onShow(() => {
|
||
hasDownload.value = false;
|
||
downLoadStatus.value = 'start';
|
||
console.log('onShow');
|
||
syncTasksFromStore();
|
||
// 监听store变化
|
||
downloadStore.addListener((tasks) => {
|
||
downloadTasks.value = tasks;
|
||
|
||
});
|
||
// 恢复正在下载的任务
|
||
resumeDownloadingTasks();
|
||
console.log('tasks');
|
||
console.log(downloadTasks.value);
|
||
if(downloadTasks.value.length > 0) {
|
||
for(let i = 0; i < downloadTasks.value.length; i++) {
|
||
if(downloadTasks.value[i].id == video_uuid.value) {
|
||
console.log('runing');
|
||
console.log(downloadTasks.value[i].status);
|
||
hasDownload.value = true;
|
||
if(downloadTasks.value[i].status == 'completed') {
|
||
downLoadStatus.value = 'completed';
|
||
}else if(downloadTasks.value[i].status == 'downloading') {
|
||
uni.showToast({
|
||
title: '视频缓存中',
|
||
icon: 'none',
|
||
});
|
||
hasDownload.value = true;
|
||
downLoadStatus.value = 'loading';
|
||
}else if(downloadTasks.value[i].status == 'paused') {
|
||
hasDownload.value = true;
|
||
downLoadStatus.value = 'loading';
|
||
}else if(downloadTasks.value[i].status == 'failed') {
|
||
hasDownload.value = true;
|
||
downLoadStatus.value = 'loading';
|
||
}
|
||
}
|
||
}
|
||
};
|
||
if (activeTab.value == "comment") {
|
||
videoCommentListV2();
|
||
}
|
||
if(from.value != 'download') {
|
||
videoDetail();
|
||
}
|
||
uni.hideLoading();
|
||
|
||
});
|
||
|
||
const shareRef = ref();
|
||
// 分享APP
|
||
const shareToggle = () => {
|
||
shareRef.value.open();
|
||
};
|
||
|
||
// 关闭分享弹窗
|
||
const closeShare = () => {
|
||
shareRef.value.close();
|
||
};
|
||
|
||
// 分享到微信
|
||
const shareToWechat = () => {
|
||
// #ifdef APP-PLUS
|
||
// 使用系统分享
|
||
|
||
uni.share({
|
||
provider: "weixin",
|
||
scene: "WXSceneSession",
|
||
type: 0,
|
||
title: videoInfo.value.name,
|
||
summary: videoInfo.value.note,
|
||
href: shareLink.value,
|
||
imageUrl: docUrl + videoInfo.value.imgpath,
|
||
success: function (res) {
|
||
//console.log("success:" + JSON.stringify(res));
|
||
},
|
||
fail: function (err) {
|
||
//console.log("fail:" + JSON.stringify(err));
|
||
},
|
||
});
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
// H5环境下的分享
|
||
if (navigator.share) {
|
||
navigator
|
||
.share({
|
||
title: "肝胆相照APP",
|
||
text: "专业的医疗健康平台,快来下载体验吧!",
|
||
url: shareLink.value,
|
||
})
|
||
.then(() => {
|
||
uni.showToast({
|
||
title: "分享成功",
|
||
icon: "success",
|
||
});
|
||
})
|
||
.catch(() => {
|
||
uni.showToast({
|
||
title: "分享失败",
|
||
icon: "none",
|
||
});
|
||
});
|
||
} else {
|
||
// 复制到剪贴板
|
||
uni.setClipboardData({
|
||
data:
|
||
"肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:" +
|
||
shareLink.value,
|
||
success: () => {
|
||
uni.showToast({
|
||
title: "已复制到剪贴板",
|
||
icon: "success",
|
||
});
|
||
},
|
||
});
|
||
}
|
||
// #endif
|
||
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序分享
|
||
uni.showShareMenu({
|
||
withShareTicket: true,
|
||
menus: ["shareAppMessage", "shareTimeline"],
|
||
});
|
||
// #endif
|
||
|
||
closeShare();
|
||
};
|
||
|
||
// 分享到朋友圈
|
||
const shareToMoments = () => {
|
||
// #ifdef APP-PLUS
|
||
uni.share({
|
||
provider: "weixin",
|
||
scene: "WXSceneTimeline",
|
||
type: 0,
|
||
title: videoInfo.value.name,
|
||
summary: videoInfo.value.note,
|
||
href: shareLink.value,
|
||
imageUrl: docUrl + videoInfo.value.imgpath,
|
||
success: function (res) {
|
||
//console.log("success:" + JSON.stringify(res));
|
||
},
|
||
fail: function (err) {
|
||
//console.log("fail:" + JSON.stringify(err));
|
||
},
|
||
});
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
// 复制到剪贴板
|
||
uni.setClipboardData({
|
||
data: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:https://www.igandan.com",
|
||
success: () => {
|
||
uni.showToast({
|
||
title: "已复制到剪贴板,可分享到朋友圈",
|
||
icon: "success",
|
||
});
|
||
},
|
||
});
|
||
// #endif
|
||
|
||
// #ifdef MP-WEIXIN
|
||
uni.showShareMenu({
|
||
withShareTicket: true,
|
||
menus: ["shareAppMessage", "shareTimeline"],
|
||
});
|
||
// #endif
|
||
|
||
closeShare();
|
||
};
|
||
|
||
// 分享到新浪微博
|
||
const shareToWeibo = () => {
|
||
// #ifdef APP-PLUS
|
||
uni.share({
|
||
provider: "sinaweibo",
|
||
type: 0,
|
||
title: videoInfo.value.name,
|
||
summary: videoInfo.value.note,
|
||
href: shareLink.value,
|
||
imageUrl: logoImg,
|
||
success: function (res) {
|
||
//console.log("分享成功");
|
||
},
|
||
fail: function (err) {
|
||
//console.log("fail:" + JSON.stringify(err));
|
||
},
|
||
});
|
||
// plus.share.sendWithSystem({
|
||
// type: 'text',
|
||
// content: '肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:https://www.igandan.com'
|
||
// }, () => {
|
||
// uni.showToast({
|
||
// title: '分享成功',
|
||
// icon: 'success'
|
||
// })
|
||
// }, (err) => {
|
||
// console.log('分享失败:', err)
|
||
// uni.showToast({
|
||
// title: '分享失败',
|
||
// icon: 'none'
|
||
// })
|
||
// })
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
// 复制到剪贴板
|
||
uni.setClipboardData({
|
||
data: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:https://www.igandan.com",
|
||
success: () => {
|
||
uni.showToast({
|
||
title: "已复制到剪贴板,可分享到微博",
|
||
icon: "success",
|
||
});
|
||
},
|
||
});
|
||
// #endif
|
||
|
||
closeShare();
|
||
};
|
||
const from = ref('');
|
||
// 使用uni-app的onLoad生命周期
|
||
onLoad((options) => {
|
||
uni.getSystemInfo({
|
||
success: function (res) {
|
||
videoWidth.value = res.windowWidth; // 窗口宽度
|
||
},
|
||
});
|
||
video_uuid.value = options.id;
|
||
from.value = options.from;
|
||
if(from.value != 'download') {
|
||
addVideoWatchRecord();
|
||
VideoDownloadRecord();
|
||
getWelfareNum();
|
||
}
|
||
|
||
// 从store同步任务列表
|
||
syncTasksFromStore();
|
||
// 监听store变化
|
||
downloadStore.addListener((tasks) => {
|
||
downloadTasks.value = tasks;
|
||
|
||
});
|
||
// 恢复正在下载的任务
|
||
resumeDownloadingTasks();
|
||
if(from.value == 'download') {
|
||
downloadTasks.value.forEach(item => {
|
||
if(item.id == video_uuid.value) {
|
||
console.log(222222);
|
||
console.log(item.localPath);
|
||
videoSrc.value = item.localPath;
|
||
showVideo.value = true;
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
// navTo({
|
||
// url: "/pages_app/downLoadVideo/downLoadVideo",
|
||
// });
|
||
});
|
||
|
||
const videoSrc = ref("");
|
||
const activeTab = ref("info");
|
||
const introText = ref(
|
||
"首都医科大学附属北京佑安医院,肝病中心四科主任(疑难肝病与人工肝中心主任),主任医师,教授,博士生导师。中华医学会肝病学分会副秘书长、委员、终末期肝病学组副组长,北京医学会肝病学分会常委,肝衰竭及人工肝学组副组长,北京肝胆相照公益基金会副理事长等。发表论文500余篇,累计SCI论文150余篇,出版专著20余部,获得科研奖项10余项,获得发明专利7项。"
|
||
);
|
||
|
||
// 示例评论数据
|
||
const commentList = ref([]);
|
||
|
||
const switchTab = (tab) => {
|
||
activeTab.value = tab;
|
||
if (tab == "comment") {
|
||
videoCommentListV2();
|
||
}
|
||
};
|
||
const payVideoDownload = async () => {
|
||
const res = await api.payVideoDownload({ video_uuid: video_uuid.value });
|
||
if (res.code == 200) {
|
||
addDownloadTask({
|
||
url: videoSrc.value,
|
||
id: video_uuid.value,
|
||
imgpath: videoInfo.value.imgpath,
|
||
author: videoInfo.value.public_name,
|
||
name: videoInfo.value.name,
|
||
});
|
||
|
||
} else if (res.code == 106) {
|
||
notEnoughVisible.value = true;
|
||
notEnoughContent.value = `您的积分不足,是否购买积分?`;
|
||
}
|
||
};
|
||
|
||
const onDownload = () => {
|
||
if (!isVideoDownloadRecord.value) {
|
||
if(welfareNum.value <= 0) {
|
||
pointContent.value = `当前需要${videoInfo.value.point}积分兑换,若删除可以再次缓存`;
|
||
uni.getNetworkType({
|
||
success: function (res) {
|
||
if (res.networkType != "none") {
|
||
networkVisible.value = true;
|
||
networkContent.value = `当前为${res.networkType}网络,确定下载?`;
|
||
} else {
|
||
uni.showToast({ title: "当前未联网,请检查网络", icon: "none" });
|
||
}
|
||
},
|
||
});
|
||
}else{
|
||
uni.getNetworkType({
|
||
success: function (res) {
|
||
if (res.networkType != "none") {
|
||
networkVisible.value = true;
|
||
networkContent.value = `当前为${res.networkType}网络,确定下载?`;
|
||
} else {
|
||
uni.showToast({ title: "当前未联网,请检查网络", icon: "none" });
|
||
}
|
||
},
|
||
});
|
||
}
|
||
|
||
|
||
} else {
|
||
if (hasDownload.value) {
|
||
navTo({
|
||
url: "/pages_app/downLoadVideo/downLoadVideo",
|
||
});
|
||
} else {
|
||
addDownloadTask({
|
||
url: videoSrc.value,
|
||
id: video_uuid.value,
|
||
imgpath: videoInfo.value.imgpath,
|
||
author: videoInfo.value.public_name,
|
||
name: videoInfo.value.name,
|
||
});
|
||
}
|
||
}
|
||
};
|
||
|
||
const goBack = () => {
|
||
uni.navigateBack();
|
||
};
|
||
const addCommentV2 = async () => {
|
||
const res = await api.addCommentV2({
|
||
article_uuid: video_uuid.value,
|
||
type: "8",
|
||
comment: commentText.value,
|
||
});
|
||
if (res.code == 200) {
|
||
uni.showToast({ title: "评论成功", icon: "none" });
|
||
commentText.value = "";
|
||
videoCommentListV2();
|
||
}
|
||
};
|
||
const onReply = (c) => {
|
||
navTo({
|
||
url:
|
||
"/pages_app/reply/reply?comment_partent=" +
|
||
c.content +
|
||
"&name=" +
|
||
c.name +
|
||
"&video_uuid=" +
|
||
video_uuid.value,
|
||
});
|
||
};
|
||
|
||
// 评论输入
|
||
const commentText = ref("");
|
||
const sendComment = () => {
|
||
if (!commentText.value.trim()) {
|
||
uni.showToast({ title: "请输入内容", icon: "none" });
|
||
return;
|
||
}
|
||
addCommentV2();
|
||
};
|
||
|
||
// 上拉加载
|
||
const page = ref(1);
|
||
const pageSize = ref(10);
|
||
const loading = ref(false);
|
||
const noMore = ref(false);
|
||
|
||
const onScrollToLower = async () => {
|
||
if (activeTab.value !== "comment" || loading.value || noMore.value) return;
|
||
// 如需分页,可在此按页码调用接口并 push 结果
|
||
};
|
||
|
||
const toFullUrl = (p) => {
|
||
if (!p) return "/static/icon_home_my_public.png";
|
||
return p.startsWith("http") ? p : docUrl + p;
|
||
};
|
||
|
||
const mapComment = (item) => {
|
||
return {
|
||
avatar: toFullUrl(item.photo || ""),
|
||
name: item.name || "匿名",
|
||
content: item.content || "",
|
||
time: item.create_date || "",
|
||
children: Array.isArray(item.childs) ? item.childs.map(mapComment) : [],
|
||
};
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
$nav-h: 140rpx;
|
||
$bottom-h: 100rpx;
|
||
$bg-color: #f7f7f7;
|
||
$text-primary: #333;
|
||
$text-secondary: #666;
|
||
$theme-color: #8b2316;
|
||
.collect-img {
|
||
/* margin-top:50rpx; */
|
||
}
|
||
.navbox {
|
||
:deep(.uni-navbar__header-btns-right) {
|
||
width: 100px !important;
|
||
}
|
||
:deep(.uni-navbar__header-btns-left) {
|
||
min-width: 100px;
|
||
width: 100px !important;
|
||
}
|
||
}
|
||
.share-img-icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
.collect-img-icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
.nav-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.video-detail-page {
|
||
border-top: 2rpx solid #cccccc;
|
||
background: $bg-color;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.content-scroll {
|
||
height: 100%;
|
||
}
|
||
|
||
.player-wrapper {
|
||
background: #fff;
|
||
position: relative;
|
||
top: calc(var(--status-bar-height) + 44px);
|
||
z-index: 0;
|
||
|
||
overflow: hidden;
|
||
}
|
||
.share-img {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
}
|
||
|
||
.tabs {
|
||
background: #fff;
|
||
display: flex;
|
||
justify-content: center;
|
||
position: fixed;
|
||
top: calc(var(--status-bar-height) + 44px + 220px);
|
||
padding: 24rpx 0 0;
|
||
|
||
|
||
width: 100%;
|
||
z-index: 99;
|
||
|
||
.tab {
|
||
width: 120rpx;
|
||
position: relative;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding: 16rpx 0 24rpx;
|
||
color: $text-secondary;
|
||
font-size: 28rpx!important;
|
||
.tab-line {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 64rpx;
|
||
height: 6rpx;
|
||
z-index: 2;
|
||
border-radius: 6rpx;
|
||
background: $theme-color;
|
||
}
|
||
&:nth-child(2) {
|
||
display: flex;
|
||
margin-left: 200rpx;
|
||
justify-content: center;
|
||
align-items: center;
|
||
text-align: center;
|
||
}
|
||
&.active {
|
||
color: $theme-color;
|
||
}
|
||
|
||
// &.active::after {
|
||
// content: "";
|
||
// position: absolute;
|
||
// left: 50%;
|
||
// bottom: 0;
|
||
// transform: translateX(-50%);
|
||
// width: 64rpx;
|
||
// height: 6rpx;
|
||
// border-radius: 6rpx;
|
||
// background: $theme-color;
|
||
// }
|
||
}
|
||
}
|
||
.video-detail-page {
|
||
position: fixed;
|
||
width: 100%;
|
||
background: #fff;
|
||
// padding: 24rpx 28rpx 40rpx;
|
||
top: calc(var(--status-bar-height) + 44px + 220px + 99rpx);
|
||
height: calc(100vh - var(--status-bar-height) - 44px - 220px - 90rpx);
|
||
overflow-y: scroll;
|
||
// background: red;
|
||
}
|
||
.intro {
|
||
// background: #fff;
|
||
padding: 30rpx 28rpx 100rpx;
|
||
// margin-top: calc(var(--status-bar-height) + 44px + 220px + 88rpx);
|
||
// height: calc(100vh - var(--status-bar-height) - 44px - 220px - 88rpx);
|
||
// overflow-y: scroll;
|
||
// padding-bottom: 100rpx;
|
||
.video-info {
|
||
margin-bottom: 20rpx;
|
||
padding: 20rpx;
|
||
background: #f8f9fa;
|
||
border-radius: 8rpx;
|
||
|
||
.video-title {
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
margin-bottom: 8rpx;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.video-author {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
|
||
.speaker {
|
||
font-size: 32rpx;
|
||
color: $text-primary;
|
||
margin: 12rpx 0 20rpx;
|
||
}
|
||
|
||
.intro-text {
|
||
font-size: 30rpx;
|
||
line-height: 1.8;
|
||
color: $text-primary;
|
||
}
|
||
}
|
||
|
||
.comments {
|
||
// background: #fff;
|
||
// margin-top: calc(var(--status-bar-height) + 44px + 220px + 88rpx);
|
||
// height: calc(100vh - var(--status-bar-height) - 44px - 220px - 88rpx);
|
||
// overflow-y: scroll;
|
||
// padding-bottom: 100rpx;
|
||
padding: 20rpx 20rpx 40rpx;
|
||
|
||
.empty {
|
||
text-align: center;
|
||
color: $text-secondary;
|
||
padding: 60rpx 0;
|
||
}
|
||
|
||
.comment-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
padding: 24rpx 10rpx;
|
||
border-bottom: 2rpx solid #f0f0f0;
|
||
|
||
.avatar {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 20rpx;
|
||
margin-right: 20rpx;
|
||
background: #eee;
|
||
}
|
||
|
||
.meta {
|
||
flex: 1;
|
||
min-width: 0;
|
||
|
||
.name {
|
||
font-size: 30rpx;
|
||
color: #1f1f1f;
|
||
margin-bottom: 6rpx;
|
||
}
|
||
|
||
.content {
|
||
font-size: 30rpx;
|
||
color: #666;
|
||
line-height: 1.6;
|
||
margin-bottom: 12rpx;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.time {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
}
|
||
}
|
||
|
||
.reply-btn {
|
||
margin-left: 16rpx;
|
||
border: 2rpx solid #8b2316;
|
||
color: #8b2316;
|
||
border-radius: 36rpx;
|
||
padding: 10rpx 24rpx;
|
||
font-size: 26rpx;
|
||
white-space: nowrap;
|
||
}
|
||
}
|
||
|
||
.list-loading,
|
||
.list-no-more {
|
||
text-align: center;
|
||
color: #9aa0a6;
|
||
padding: 20rpx 0;
|
||
font-size: 26rpx;
|
||
}
|
||
.child-list {
|
||
margin-top: 8rpx;
|
||
margin-left: -10rpx;
|
||
}
|
||
.child-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-top: 16rpx;
|
||
}
|
||
.avatar.small {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
border-radius: 12rpx;
|
||
margin-right: 16rpx;
|
||
}
|
||
}
|
||
|
||
.bottom-spacer {
|
||
height: 40rpx;
|
||
}
|
||
|
||
.bottom-download {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
height: $bottom-h;
|
||
background: #00cac1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 10;
|
||
.discount {
|
||
color: #d4ff00;
|
||
font-size: 40rpx;
|
||
}
|
||
.download-text {
|
||
color: #fff;
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
|
||
.bottom-comment {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
height: 100rpx;
|
||
background: #ffffff;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 20rpx;
|
||
gap: 16rpx;
|
||
z-index: 10;
|
||
|
||
.comment-input {
|
||
flex: 1;
|
||
height: 72rpx;
|
||
border-radius: 10rpx;
|
||
background: #ffffff;
|
||
border: 2rpx solid #cacaca;
|
||
padding: 0 24rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.send-btn {
|
||
padding: 0 28rpx;
|
||
height: 72rpx;
|
||
border-radius: 36rpx;
|
||
background: #8b2316;
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
|
||
/* 分享弹窗样式 */
|
||
.share-popup {
|
||
background-color: #fff;
|
||
border-radius: 20rpx 20rpx 0 0;
|
||
padding: 40rpx 0 0;
|
||
}
|
||
|
||
.share-title {
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
margin-bottom: 40rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.share-content {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding: 0 40rpx 40rpx;
|
||
}
|
||
|
||
.share-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
flex: 1;
|
||
}
|
||
|
||
.share-icon {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.wechat-icon {
|
||
background-color: #07c160;
|
||
}
|
||
|
||
.moments-icon {
|
||
background-color: #07c160;
|
||
}
|
||
|
||
.weibo-icon {
|
||
background-color: #e6162d;
|
||
}
|
||
|
||
.qq-icon {
|
||
background-color: #12b7f5;
|
||
}
|
||
|
||
.share-icon-text {
|
||
font-size: 50rpx;
|
||
color: #fff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.share-text {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.share-cancel {
|
||
height: 100rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-top: 1rpx solid #f0f0f0;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.share-cancel:active {
|
||
background-color: #f5f5f5;
|
||
}
|
||
</style> |