mirror of
https://github.com/fireinrain/JHS-enhance.git
synced 2026-10-01 00:26:39 +08:00
120 lines
9.4 KiB
JavaScript
120 lines
9.4 KiB
JavaScript
import { BasePlugin } from '../core/base-plugin.js';
|
|
import { __publicField, qualityOptions } from '../core/constants.js';
|
|
import {getDmmVideo, selectDefaultQuality} from '../api/dmm.js';
|
|
|
|
class BusPreviewVideoPlugin extends BasePlugin {
|
|
getName() {
|
|
return "BusPreviewVideoPlugin";
|
|
}
|
|
|
|
async initCss() {
|
|
return "\n /* 弹窗/Modal 样式 */\n .bus-preview-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.95); \n /* 关键修改:更新 z-index */\n z-index: 12345699; \n display: flex;\n justify-content: center;\n align-items: center;\n opacity: 0; \n visibility: hidden; \n transition: opacity 0.2s ease;\n }\n .bus-preview-modal.is-open {\n opacity: 1;\n visibility: visible;\n }\n /* 垂直排列视频和按钮,并居中 */\n .bus-preview-modal-content {\n position: relative;\n max-width: 95%; \n max-height: 95%;\n display: flex; \n flex-direction: column; \n align-items: center; \n gap: 15px; \n }\n \n /* 移除 .bus-preview-close-btn 的样式 */\n\n /* 视频播放器容器 */\n .video-player-wrapper {\n /* 关键修改:更新 width 和 max-height */\n width: 80vw; \n max-height: 85vh; \n aspect-ratio: 16 / 9; \n position: relative; \n background-color: black; \n max-width: 100%; \n }\n /* 视频元素 */\n .video-player-wrapper #preview-video {\n position: absolute; \n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: block;\n }\n\n /* 画质控制盒 (底部按钮) */\n .video-control-box {\n display: flex;\n flex-direction: row; \n justify-content: center; \n flex-wrap: wrap; \n gap: 10px;\n padding: 10px 0; \n }\n\n /* 按钮样式 (保留) */\n .video-control-btn {\n min-width:80px;\n padding: 6px 12px;\n background: rgba(255,255,255,0.2);\n color: white;\n border: 1px solid rgba(255,255,255,0.5);\n border-radius: 4px;\n cursor: pointer;\n text-align: center;\n font-size: 14px;\n transition: background-color 0.2s, border-color 0.2s;\n }\n .video-control-btn:hover {\n background: rgba(255,255,255,0.4);\n }\n .video-control-btn.active {\n background-color: #1890ff; \n color: white;\n font-weight: bold;\n border: 1px solid #096dd9;\n }\n ";
|
|
}
|
|
initModal() {
|
|
if (0 === $("#bus-preview-modal").length) {
|
|
$("body").append('\n <div id="bus-preview-modal" class="bus-preview-modal">\n <div class="bus-preview-modal-content">\n </div>\n </div>\n ');
|
|
const $modal = $("#bus-preview-modal");
|
|
$modal.on("click", (e => {
|
|
"bus-preview-modal" === e.target.id && this.closeVideoModal();
|
|
}));
|
|
$(document).on("keydown", (e => {
|
|
"Escape" === e.key && $modal.hasClass("is-open") && this.closeVideoModal();
|
|
}));
|
|
}
|
|
}
|
|
closeVideoModal() {
|
|
const $previewVideo = $("#preview-video");
|
|
if ($previewVideo.length > 0) {
|
|
const videoEl = $previewVideo[0];
|
|
videoEl.pause();
|
|
}
|
|
$("#bus-preview-modal").removeClass("is-open");
|
|
}
|
|
async handle() {
|
|
if (!window.isDetailPage) return;
|
|
this.initModal();
|
|
const firstImageSrc = $("#sample-waterfall .sample-box .photo-frame img:first").attr("src"), videoPreview = $(`\n <a class="preview-video-container sample-box" style="cursor: pointer">\n <div class="photo-frame" style="position:relative;">\n <img src="${firstImageSrc}" class="video-cover" alt="">\n <div class="play-icon" style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); \n color:white; font-size:40px; text-shadow:0 0 10px rgba(0,0,0,0.5);">\n ▶\n </div>\n </div>\n </a>`);
|
|
$("#sample-waterfall").prepend(videoPreview);
|
|
"yes" === await storageManager.getSetting("enableLoadPreviewVideo", "yes") && getDmmVideo(this.getPageInfo().carNum, !1).then();
|
|
let isHandlingVideo = !1, $preview = $(".preview-video-container");
|
|
$preview.on("click", (async event => {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
if (isHandlingVideo) show.info("正在加载中, 勿重复点击"); else {
|
|
isHandlingVideo = !0;
|
|
try {
|
|
await this.handleVideo();
|
|
} finally {
|
|
isHandlingVideo = !1;
|
|
}
|
|
}
|
|
}));
|
|
window.location.href.includes("autoPlay=1") && $preview.trigger("click");
|
|
}
|
|
async handleVideo() {
|
|
const $modal = $("#bus-preview-modal"), $modalContent = $modal.find(".bus-preview-modal-content");
|
|
let $previewVideo = $("#preview-video");
|
|
if ($previewVideo.length > 0) {
|
|
$modal.addClass("is-open");
|
|
const videoEl = $previewVideo[0];
|
|
videoEl.play().catch((e => console.warn("尝试播放失败 (可能被浏览器阻止):", e)));
|
|
return;
|
|
}
|
|
let carNum2 = this.getPageInfo().carNum;
|
|
const dmmVideoMap = await getDmmVideo(carNum2);
|
|
if (dmmVideoMap && 0 !== Object.keys(dmmVideoMap).length) {
|
|
await this.createVideoPlayerAndControls(dmmVideoMap, $modalContent);
|
|
$previewVideo = $("#preview-video");
|
|
if ($previewVideo.length > 0) {
|
|
$modal.addClass("is-open");
|
|
$previewVideo[0].play().catch((e => console.warn("尝试播放失败 (可能被浏览器阻止):", e)));
|
|
} else show.error("视频播放器创建失败。");
|
|
} else show.error("未找到可用的视频源。");
|
|
}
|
|
async createVideoPlayerAndControls(dmmVideoMap, $container) {
|
|
let defaultVideoQuality = await storageManager.getSetting("videoQuality");
|
|
defaultVideoQuality = selectDefaultQuality(Object.keys(dmmVideoMap), defaultVideoQuality);
|
|
let defaultVideoUrl = dmmVideoMap[defaultVideoQuality];
|
|
$container.html(`\n <div class="video-player-wrapper">\n <video id="preview-video" controls playsinline>\n <source src="${defaultVideoUrl}" />\n </video>\n </div>\n <div class="video-control-box">\n </div>\n `);
|
|
const $videoEl = $("#preview-video"), $qualityControlsBox = $container.find(".video-control-box");
|
|
if (!$videoEl.length) return;
|
|
const videoEl = $videoEl[0];
|
|
const jhs_videoMuted = localStorage.getItem("jhs_videoMuted");
|
|
videoEl.muted = !jhs_videoMuted || "yes" === jhs_videoMuted;
|
|
videoEl.addEventListener("volumechange", (function() {
|
|
localStorage.setItem("jhs_videoMuted", videoEl.muted ? "yes" : "no");
|
|
}));
|
|
|
|
let buttonsHtml = "";
|
|
qualityOptions.forEach((option => {
|
|
let dmmVideoUrl = dmmVideoMap[option.quality];
|
|
if (dmmVideoUrl) {
|
|
const isActive = defaultVideoQuality === option.quality;
|
|
buttonsHtml += `\n <button class="video-control-btn${isActive ? " active" : ""}" \n data-quality="${option.quality}"\n data-video-src="${dmmVideoUrl}">\n ${option.text}\n </button>\n `;
|
|
}
|
|
}));
|
|
$qualityControlsBox.html(buttonsHtml);
|
|
const $buttons = $qualityControlsBox.find(".video-control-btn");
|
|
$qualityControlsBox.off("click").on("click", ".video-control-btn", (async e => {
|
|
try {
|
|
const $button = $(e.currentTarget);
|
|
if ($button.hasClass("active")) return;
|
|
let videoSrc = $button.attr("data-video-src");
|
|
const currentTime = videoEl.currentTime;
|
|
videoEl.src = videoSrc;
|
|
videoEl.load();
|
|
if (currentTime > 0 && Number.isFinite(currentTime)) {
|
|
videoEl.currentTime = currentTime;
|
|
}
|
|
await videoEl.play();
|
|
$buttons.removeClass("active");
|
|
$button.addClass("active");
|
|
} catch (error) {
|
|
console.error("切换画质失败:", error);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
|
|
export { BusPreviewVideoPlugin }; |