ow
This commit is contained in:
1 parent
2e1974c35d
commit
9cf69dee5d
3 files changed
+84
-6
No files matched your search
@@ -24,6 +24,12 @@
|
|||||||
@click.stop="toggle">
|
@click.stop="toggle">
|
||||||
<CaretRightFilled />
|
<CaretRightFilled />
|
||||||
</button>
|
</button>
|
||||||
|
<!-- 控制区收起后画面上留一个恢复入口:影视厅这种整页用法没有弹窗右上角按钮,
|
||||||
|
否则收起后就再也点不回来了 -->
|
||||||
|
<button v-if="!controlsVisible" class="vp-restore" type="button" title="显示控制区"
|
||||||
|
@click.stop="toggleControls">
|
||||||
|
<EyeOutlined />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 控制区:单击画面区可隐藏,隐藏后画面区吃掉这部分空间 -->
|
<!-- 控制区:单击画面区可隐藏,隐藏后画面区吃掉这部分空间 -->
|
||||||
@@ -861,6 +867,30 @@ onBeforeUnmount(() => {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 控制区收起后留在画面右下角的「显示控制区」入口 */
|
||||||
|
.vp-restore {
|
||||||
|
position: absolute;
|
||||||
|
right: 14px;
|
||||||
|
bottom: 14px;
|
||||||
|
z-index: 3;
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(6, 56, 62, 0.5);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.45);
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vp-restore:active {
|
||||||
|
transform: scale(0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------- 功能图标行 ---------- */
|
/* ---------- 功能图标行 ---------- */
|
||||||
|
|||||||
@@ -370,21 +370,29 @@ const clearRefreshTimers = () => {
|
|||||||
const onUploadComplete = (payload: { count?: number }) => {
|
const onUploadComplete = (payload: { count?: number }) => {
|
||||||
const count = payload?.count ?? 1;
|
const count = payload?.count ?? 1;
|
||||||
const sec = 2500 + (count - 1) * 1000;
|
const sec = 2500 + (count - 1) * 1000;
|
||||||
|
// 本次是不是视频:只有视频才需要补刷和转码提示
|
||||||
|
const isVideo = uploadingVideo.value;
|
||||||
// 视频场景由转码提示接管文案,等首刷完成后再切回"加载中..."
|
// 视频场景由转码提示接管文案,等首刷完成后再切回"加载中..."
|
||||||
if (!uploadingVideo.value) spinTip.value = "加载中...";
|
if (!isVideo) spinTip.value = "加载中...";
|
||||||
clearRefreshTimers();
|
clearRefreshTimers();
|
||||||
|
|
||||||
refreshTimers.push(
|
refreshTimers.push(
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
// 列表已经刷出来了,转码提示到此为止(后续补刷沿用默认的"加载中...")
|
// 列表已经刷出来了,转码提示到此为止
|
||||||
stopTranscodeTip();
|
stopTranscodeTip();
|
||||||
uploadingVideo.value = false;
|
uploadingVideo.value = false;
|
||||||
onReSearch();
|
onReSearch();
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}, sec),
|
}, sec),
|
||||||
);
|
);
|
||||||
refreshTimers.push(window.setTimeout(onReSearch, sec + 3000));
|
|
||||||
refreshTimers.push(window.setTimeout(onReSearch, sec + 6000));
|
// 只有视频才补刷:封面(jpg)是服务端 ffmpeg 异步生成的,首刷时可能还没落盘;
|
||||||
|
// 每次查询服务端都会重新拼 ?v=,src 变了 <img> 才会重新请求,封面就能补上来。
|
||||||
|
// 图片/音频/普通文件上传后文件已经就绪,一次刷新就够,多刷纯属浪费。
|
||||||
|
if (isVideo) {
|
||||||
|
refreshTimers.push(window.setTimeout(onReSearch, sec + 3000));
|
||||||
|
refreshTimers.push(window.setTimeout(onReSearch, sec + 6000));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 中断时的断点信息,弹窗里展示用 */
|
/** 中断时的断点信息,弹窗里展示用 */
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
<div class="pv-page" :style="{
|
<div class="pv-page" :style="{
|
||||||
height: bsInfo.height - 120 + 'px',
|
height: bsInfo.height - 120 + 'px',
|
||||||
}">
|
}">
|
||||||
<VideoPlayer :videos="videos" />
|
<VideoPlayer v-model:controls="controlsVisible" :videos="videos" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted, onUnmounted, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
import VideoPlayer from "@/components/basic/VideoPlayer.vue";
|
import VideoPlayer from "@/components/basic/VideoPlayer.vue";
|
||||||
@@ -32,6 +32,21 @@ const mode = ref<string>(route.params.mode as string);
|
|||||||
// 视频列表:与 VinylAudioPlayer 的 tracks 一致,组件负责 UI,页面只负责数据
|
// 视频列表:与 VinylAudioPlayer 的 tracks 一致,组件负责 UI,页面只负责数据
|
||||||
const videos = ref<VideoItem[]>([]);
|
const videos = ref<VideoItem[]>([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 底部控制区显隐(点播放器控制栏里的眼睛图标切换)。
|
||||||
|
* 影视厅是整页用法,收起控制区时连 layout 顶部的两条栏(标题栏 + 页面头)一起藏掉,
|
||||||
|
* 视频才能占满整屏。class 挂在 body 上,离开本页/恢复显示时立即移除,不会影响其它页面。
|
||||||
|
*/
|
||||||
|
const controlsVisible = ref(true);
|
||||||
|
|
||||||
|
watch(controlsVisible, (visible) => {
|
||||||
|
document.body.classList.toggle("pv-fullscreen", !visible);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.body.classList.remove("pv-fullscreen");
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadVideos();
|
await loadVideos();
|
||||||
});
|
});
|
||||||
@@ -113,4 +128,29 @@ const loadVideos = async () => {
|
|||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* 注意:这里是全局样式,但所有选择器都要求 body 上有 .pv-fullscreen
|
||||||
|
(只在影视厅收起控制区时由 PreviewVideo.vue 临时挂上,离开页面即移除),
|
||||||
|
所以不会影响其它页面。
|
||||||
|
|
||||||
|
收起控制区 = 页面全屏:
|
||||||
|
1. 藏掉 layout 顶部两条栏(标题栏 64px + 页面头 42px);
|
||||||
|
2. 内容区和视频容器撑到整屏,去掉原有的 8px 内边距,做到真正的全屏铺满。
|
||||||
|
容器高度是行内样式(bsInfo.height - 100/-120),只能用 !important 覆盖。 */
|
||||||
|
body.pv-fullscreen .layout-header,
|
||||||
|
body.pv-fullscreen .layout-page-header {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.pv-fullscreen .layout-content-view {
|
||||||
|
height: 100vh !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.pv-fullscreen .pv-page {
|
||||||
|
height: 100vh !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in new issue
Block a user