import { BilibiliData } from "@/data/BlibiliData"; import { $, $$, DOMUtils, addStyle, log, utils } from "@/env"; import { MobileCommentModule } from "@/lib/MobileCommentModule"; import MobileCommentModuleStyle from "@/lib/MobileCommentModule.css?raw"; import { BilibiliUrl } from "@/utils/BilibiliUrl"; import { BilibiliUtils } from "@/utils/BilibiliUtils"; import { GM_RESOURCE_MAPPING } from "@components/GM_Resource_Mapping"; import { Panel } from "@components/setting/panel"; import { CommonUtil } from "@components/utils/CommonUtil"; import { GestureBack } from "@components/utils/GestureBack"; import { VueUtils } from "@components/utils/VueUtils"; import type { Vue2Instance } from "@whitesev/utils/dist/types/src/types/Vue2.js"; import Qmsg from "qmsg"; import { BilibiliVideoPlayer } from "./BilibiliVideoPlayer"; export const BilibiliVideo = { $data: { /** 是否已添加美化CSS */ isAddBeautifyCSS: false, /** 是否已经初始化评论模块 */ isInitCommentModule: false, /** 是否已经初始化简介模块 */ isInitDescModule: false, }, init() { BilibiliVideoPlayer.init(); /* 执行hook */ // Panel.execMenuOnce("bili-video-repairVideoBottomAreaHeight", () => { // return this.repairVideoBottomAreaHeight(); // }); // Panel.execMenu("bili-video-beautify", () => { // this.beautify(); // }); Panel.execMenuOnce("bili-video-cover-bottomRecommendVideo", () => { this.coverBottomRecommendVideo(); }); Panel.execMenuOnce("bili-video-cover-UpWrapper", () => { this.coverUpWrapper(); }); // Panel.execMenuOnce("bili-video-gestureReturnToCloseCommentArea", () => { // this.gestureReturnToCloseCommentArea(); // }); Panel.execMenuOnce("bili-video-cover-seasonNew", () => { this.coverSeasonNew(); }); // Panel.execMenuOnce("bili-video-repairLinkJump", () => { // this.repairLinkJump(); // }); DOMUtils.onReady(() => { // Panel.execMenuOnce("bili-video-optimizationScroll", () => { // this.optimizationScroll(); // }); // Panel.execMenu("bili-video-disableSwipeTab", () => { // this.disableSwipeTab(); // }); Panel.execMenu("bili-video-addCommentModule", () => { this.addCommentModule(); }); Panel.execMenu("bili-video-addDescModule", () => { this.addDescModule(); }); }); }, /** * 美化显示 */ beautify() { log.info("美化显示"); /* 先添加美化CSS */ if (!this.$data.isAddBeautifyCSS) { this.$data.isAddBeautifyCSS = true; addStyle(/*css*/ ` @charset "UTF-8"; ${BilibiliData.className.video} .video-list .card-box { --left-card-width: 33%; --right-child-padding: 1.333vmin; /* 开启了bili-video-beautify */ } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp { width: 100%; border-bottom: 1px solid #b5b5b5; padding-left: 0; padding-right: 0; } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a { display: flex; flex-wrap: nowrap; gap: var(--right-child-padding); } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a .card { width: var(--left-card-width); height: 80px; flex: 0 auto; } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a .card .count { background: transparent; } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a .card .count .left { display: list-item; } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a .card .count .left span.item { display: none; } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a .card .count .duration { background: rgba(0, 0, 0, 0.4); border-radius: 0.6vmin; padding: 0px 0.5vmin; right: 1vmin; bottom: 1vmin; } ${BilibiliData.className.video} .video-list .card-box .v-card-toapp > a .title { /*flex: 1;*/ /*padding: var(--right-child-padding);*/ padding-top: 0; margin-top: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container { display: flex; flex-direction: column; width: calc(100% - var(--left-card-width)); justify-content: space-between; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container > * { padding: var(--right-child-padding); padding-bottom: 0; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container .left { gap: 1rem; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container .left span { display: flex; align-items: safe center; gap: 1vmin; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container .gm-up-name, ${BilibiliData.className.video} .video-list .card-box .gm-right-container .left { color: #999; font-size: 3vmin; transform-origin: left; display: flex; /*align-items: safe center;*/ align-items: safe flex-end; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container .gm-up-name svg { width: 3vmin; height: 3vmin; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container .gm-up-name-text { margin-left: 1vmin; } ${BilibiliData.className.video} .video-list .card-box .gm-right-container .num { margin-right: 4vmin; } ${BilibiliData.className.video} .video-list .card-box > a.v-card { width: 100%; border-bottom: 1px solid #b5b5b5; padding-left: 0; padding-right: 0; display: flex; flex-wrap: nowrap; } ${BilibiliData.className.video} .video-list .card-box > a.v-card .card { width: var(--left-card-width); height: 100%; flex: 0 auto; } ${BilibiliData.className.video} .video-list .card-box > a.v-card .card .count { background: transparent; } ${BilibiliData.className.video} .video-list .card-box > a.v-card .card .count span { display: none; } ${BilibiliData.className.video} .video-list .card-box > a.v-card .card .count .duration { background-color: rgba(0, 0, 0, 0.3); border-radius: 4px; color: #fff; font-size: 12px; height: 16px; line-height: 16px; margin-left: auto; padding-left: 4px; padding-right: 4px; } ${BilibiliData.className.video} .video-list .card-box > a.v-card .title { flex: 1; /*padding: var(--right-child-padding);*/ padding-top: 0; margin-top: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } `); } DOMUtils.waitNode(BilibiliData.className.video + " .bottom-tab .list-view .card-box", 10000).then( ($cardBox) => { if (!$cardBox) { log.error("$cardBox is null"); return; } /** * 未设置isLogin的视频卡片 * @param $vCard */ function handleVCardToApp($vCard: HTMLDivElement) { // 标题 let $originTitle = $vCard.querySelector(".title"); // 左边的播放量信息 let $originLeft = $vCard.querySelector(".count .left"); // 是否已经处理过 let isHandled = Boolean($vCard.querySelector(".gm-right-container")); let vueObj = VueUtils.getVue($vCard); if ($originTitle && $originLeft && vueObj && !isHandled) { let upName: string | null = vueObj?.info?.owner?.name; if (upName == null) { log.error("美化显示-handleVCardToApp:获取up主名字失败"); return; } let $originCount = $vCard.querySelector(".count"); let $title = $originTitle.cloneNode(true) as HTMLElement; let $left = $originLeft.cloneNode(true) as HTMLElement; // 隐藏元素,不能直接修改元素的位置,回答导致页面初始化时appendChild异常 DOMUtils.hide($originTitle); if ($originCount) { // DOMUtils.hide($originCount); } // 视频封面右上角的App文字 let $isOpenAppWeakened = $vCard.querySelector(".open-app.weakened"); if ($isOpenAppWeakened) { DOMUtils.hide($isOpenAppWeakened); } let $upInfo = document.createElement("div"); $upInfo.className = "gm-up-name"; $upInfo.innerHTML = /*html*/ ` ${upName} `; // 右侧容器 let $rightContainer = document.createElement("div"); // 右侧下面的容器 let $rightBottom = document.createElement("div"); $rightContainer.className = "gm-right-container"; $rightBottom.className = "gm-right-bottom"; DOMUtils.after($originTitle, $rightContainer); /* 标题 */ $rightContainer.appendChild($title); /* 底部内容 */ $rightContainer.appendChild($rightBottom); /* UP主 */ $rightBottom.appendChild($upInfo); /* 播放量 弹幕量 */ $rightBottom.appendChild($left); } } /** * 设置了isLogin的视频卡片 * @param $vCard */ function handleVCard($vCard: HTMLDivElement) { let $originTitle = $vCard.querySelector(".title"); let $originCount = $vCard.querySelector(".count"); // 是否已经处理过 let isHandled = Boolean($vCard.querySelector(".gm-right-container")); let vueObj = VueUtils.getVue($vCard); if ($originTitle && $originCount && vueObj && !isHandled) { /* 这个里面没有播放时长,自己添加一个 */ let duration = vueObj?.info?.duration; if (duration == null) { log.error("美化显示-handleVCard:获取视频时长失败"); return; } let upName = vueObj?.info?.owner?.name; if (upName == null) { log.error("美化显示-handleVCard:获取up主名字失败"); return; } let $cloneTitle = $originTitle.cloneNode(true) as HTMLElement; let $cloneCount = $originCount.cloneNode(true) as HTMLDivElement; DOMUtils.hide($originTitle); let $duration = document.createElement("div"); $duration.className = "duration"; // 转换显示时长 $duration.innerText = BilibiliUtils.parseDuration(duration); $cloneCount.className = "left"; let $upInfo = document.createElement("div"); $originCount.appendChild($duration); $upInfo.className = "gm-up-name"; $upInfo.innerHTML = /*html*/ ` ${upName} `; let $rightContainer = document.createElement("div"); let $rightBottom = document.createElement("div"); $rightContainer.className = "gm-right-container"; $rightBottom.className = "gm-right-bottom"; DOMUtils.after($originTitle, $rightContainer); /* 标题 */ $rightContainer.appendChild($cloneTitle); /* 底部内容 */ $rightContainer.appendChild($rightBottom); /* UP主 */ $rightBottom.appendChild($upInfo); /* 播放量 弹幕量 */ $rightBottom.appendChild($cloneCount); } } let lockFunc = new utils.LockFunction(() => { let $vCardList = $$( BilibiliData.className.video + " .bottom-tab .list-view .card-box .v-card-toapp" ); let $vCardList_isLogon = $$( BilibiliData.className.video + " .bottom-tab .list-view .card-box>a.v-card" ); /* isLogin不生效的情况下 */ $vCardList.forEach((_$vCard_) => { handleVCardToApp(_$vCard_); }); /* isLogin生效 */ $vCardList_isLogon.forEach((_$vCard_) => { handleVCard(_$vCard_); }); }, 25); let $videoRoot = $(BilibiliData.className.video); if ($videoRoot) { utils.mutationObserver($videoRoot, { config: { subtree: true, attributes: true, childList: true, }, callback() { lockFunc.run(); }, }); } else { log.error("未找到视频根节点"); } } ); }, /** * 修复视频底部区域高度 */ repairVideoBottomAreaHeight() { log.info("修复视频底部区域高度"); return addStyle(/*css*/ ` ${BilibiliData.className.video}, ${BilibiliData.className.mVideo} { /* 修复视频区域底部的高度 */ .natural-module .fixed-module-margin { margin-top: 55.13333vmin; } /* 点击播放视频后的 */ .m-video-new:has(> div > .m-video-player) { margin-top: 75vmin; } /* 未播放视频状态下的 */ .m-video-new:has(> div[style*="display:none"] > .m-video-player) { margin-top: unset; } } html.tiny-app{ ${BilibiliData.className.video}, ${BilibiliData.className.mVideo}{ .m-video-info-new{ margin-top: 72vmin; } } } `); }, /** * 修复up主信息区域的点击事件 */ coverUpWrapper() { log.info(`修复up主信息区域的点击事件`); DOMUtils.on( document, "click", [ BilibiliData.className.video + " .bottom-wrapper .up-wrapper", BilibiliData.className.mVideo + " .bottom-wrapper .up-wrapper", ], function (event) { let $click = event.target as HTMLElement; let $bottomWrapper = $click.closest(".bottom-wrapper")!; if (!$bottomWrapper) { log.error("获取元素.bottom-wrapper失败"); return; } let vueInstance = VueUtils.getVue($bottomWrapper); if (!vueInstance) { log.error("获取元素.bottom-wrapper的vue实例失败"); return; } let mid = vueInstance?.upInfo?.card?.mid; if (typeof mid === "string") { BilibiliUtils.goToUrl(BilibiliUrl.getUserSpaceUrl(mid)); } else { Qmsg.error("获取mid失败"); } }, { capture: true, } ); }, /** * 覆盖视频标题区域的点击事件 */ coverBottomRecommendVideo() { log.info("覆盖 相关视频 点击事件"); DOMUtils.on( document, "click", [ BilibiliData.className.video + " .list-view .card-box .launch-app-btn", BilibiliData.className.mVideo + " .list-view .card-box .launch-app-btn", ], function (event) { let $click = event.target as HTMLDivElement; let vueObj = VueUtils.getVue($click); if (!vueObj) { Qmsg.error("获取相关视频的__vue__失败"); return; } let bvid = vueObj.bvid; if (utils.isNull(bvid)) { if (vueObj.$children && vueObj.$children[0] && utils.isNotNull(vueObj.$children[0].bvid)) { bvid = vueObj.$children[0].bvid; } else { Qmsg.error("获取相关视频的bvid失败"); return; } } log.info("相关视频的bvid: " + bvid); BilibiliUtils.goToUrl(BilibiliUrl.getVideoUrl(bvid)); DOMUtils.preventEvent(event); }, { capture: true, } ); }, /** * 覆盖选集视频列表的点击事件 */ coverSeasonNew() { log.info("覆盖 选集视频列表 点击事件"); function ClickCallBack(event: PointerEvent | MouseEvent) { let $click = event.target as HTMLDivElement; let vueObj = VueUtils.getVue($click); if (!vueObj) { Qmsg.error("获取选集视频的目标视频的__vue__失败"); return; } let bvid = vueObj.bvid; if (utils.isNull(bvid)) { Qmsg.error("获取相关视频的bvid失败"); return; } log.info("相关视频的bvid: " + bvid); BilibiliUtils.goToUrl(BilibiliUrl.getVideoUrl(bvid)); DOMUtils.preventEvent(event); } DOMUtils.on( document, "click", [ BilibiliData.className.video + " .m-video-season-new .video-card .launch-app-btn", BilibiliData.className.mVideo + " .m-video-season-new .video-card .launch-app-btn", ], ClickCallBack, { capture: true, } ); /* 查看更多 展开后的视频列表 */ DOMUtils.on( document, "click", [ BilibiliData.className.video + " .m-video-season-panel .season-video-item .launch-app-btn", BilibiliData.className.mVideo + " .m-video-season-panel .season-video-item .launch-app-btn", ], ClickCallBack, { capture: true, } ); }, /** * 修复链接跳转 */ repairLinkJump() { log.info(`修复链接跳转`); let lockFn = new utils.LockFunction(() => { ["a.member-link:not([href])[data-url]", "a.jump-link:not([href])[data-url]"].forEach((selector) => { $$(selector).forEach(($el) => { $el.href = $el.getAttribute("data-url")!; }); }); }); utils.mutationObserver(document, { config: { subtree: true, childList: true, }, callback: () => { lockFn.run(); }, }); }, /** * 手势返回关闭评论区 */ gestureReturnToCloseCommentArea() { log.info("手势返回关闭评论区,全局监听document点击.sub-reply-preview"); DOMUtils.waitNode("#app").then(($app) => { utils .waitVueByInterval( $app, () => { let vueObj = VueUtils.getVue($app as HTMLDivElement); if (vueObj == null) { return false; } return typeof vueObj?.$router?.options?.scrollBehavior != null; }, 250, 10000 ) .then((result) => { let appVue = VueUtils.getVue($app as HTMLDivElement); if (!appVue) { log.error("获取#app的vue属性失败"); return; } let oldScrollBehavior = appVue.$router.options.scrollBehavior; appVue.$router.options.scrollBehavior = function ( to: Vue2Instance["$route"], from: Vue2Instance["$route"], scrollInfo?: { x: number; y: number; } ) { if (to["hash"] === "#/seeCommentReply") { /* 打开评论区 */ log.info("当前操作为打开评论区,scrollBehavior返回null"); return null; } else if (to["hash"] === "" && from["hash"] === "#/seeCommentReply") { /* 关闭评论区 */ log.info("当前操作为关闭评论区,scrollBehavior返回null"); return null; } return oldScrollBehavior.call(this, ...arguments); }; }); }); DOMUtils.on(document, "click", ".sub-reply-preview", function (event) { let $app = $("#app"); let appVue = VueUtils.getVue($app as HTMLDivElement); if (!appVue) { log.error("获取#app元素失败"); return; } let hookGestureReturnByVueRouter = BilibiliUtils.hookGestureReturnByVueRouter({ vueInst: appVue, hash: "#/seeCommentReply", callback(isFromPopState) { if (!isFromPopState) { return false; } let $dialogCloseIcon = $(".dialog-close-icon"); if ($dialogCloseIcon) { $dialogCloseIcon.click(); } else { log.error("评论区关闭失败,原因:元素dialog-close-icon获取失败"); } return true; }, }); DOMUtils.waitNode(".dialog-close-icon").then(($dialogCloseIcon) => { DOMUtils.on( $dialogCloseIcon, "click", function () { hookGestureReturnByVueRouter.resumeBack(false); }, { capture: true, once: true, } ); }); }); }, /** * 进入全屏 */ enterVideoFullScreen() { DOMUtils.waitNode(".mplayer-btn-widescreen", 5000).then(($btnWideScreen) => { if (!$btnWideScreen) { log.error("获取全屏按钮失败"); Qmsg.error("获取全屏按钮失败"); return; } if ($btnWideScreen.closest(".mplayer-wide")) { log.warn("当前的全屏按钮是【退出全屏】,不点击"); return; } log.info(`进入全屏`); $btnWideScreen.click(); }); }, /** * 优化滚动显示view */ optimizationScroll() { /** * 顶部导航栏 */ let $mNavBar: HTMLElement | null | undefined = null; /** 视频主内容 */ let $mVideoPlayer: HTMLElement | null | undefined = null; let $mVideoInfoNew: HTMLElement | null | undefined = null; /** * 底部tab */ let $bottomTab: HTMLElement | null | undefined = null; /** * 底部tab的affix */ let $bottomTabVAffix: HTMLElement | null | undefined = null; /** 最大高度 */ let videoPlayerMaxHeight = 0; /** 最大padding-top */ let videoPlayerMaxPaddingTop = 0; /** * 判断元是否为空或者在不在页面中 */ function checkNodeIsNull(checkNode: T | null | undefined): checkNode is null | undefined { if (checkNode == null) return false; return !document.contains(checkNode); } DOMUtils.on( document, "scroll", (event) => { if (checkNodeIsNull($mVideoPlayer)) { $mVideoPlayer = $(".m-video-player"); if (checkNodeIsNull($mVideoPlayer)) { return; } if (videoPlayerMaxHeight == 0) { const videoPlayerRect = $mVideoPlayer.getBoundingClientRect(); videoPlayerMaxHeight = videoPlayerRect.height; videoPlayerMaxPaddingTop = videoPlayerRect.top; log.info(`视频区域的最大高度为 ${videoPlayerMaxHeight}px`); log.info(`视频区域的最大top为 ${videoPlayerMaxPaddingTop}px`); } } if (checkNodeIsNull($mVideoInfoNew)) { $mVideoInfoNew = $(".m-video-info-new"); if (checkNodeIsNull($mVideoInfoNew)) { return; } } if (checkNodeIsNull($mNavBar)) { $mNavBar = $(".m-navbar"); if (checkNodeIsNull($mNavBar)) { return; } } if (checkNodeIsNull($bottomTab)) { $bottomTab = $(".bottom-tab"); if (checkNodeIsNull($bottomTab)) { return; } } if (checkNodeIsNull($bottomTabVAffix)) { $bottomTabVAffix = $(".bottom-tab .v-affix"); if (checkNodeIsNull($bottomTabVAffix)) { return; } } // 自动根据video-info的top距离来设置视频的padding-top值 let videoInfoNewTop = $mVideoInfoNew.getBoundingClientRect().top; if (videoInfoNewTop >= 0) { if (videoInfoNewTop <= videoPlayerMaxHeight) { $mVideoPlayer.style.paddingTop = videoInfoNewTop + "px"; } else { $mVideoPlayer.style.paddingTop = ""; } } else { // padding-0 $mVideoPlayer.style.paddingTop = "0px"; } // 计算顶部导航栏和底部tab的距离 // 也就是底部tab的top距离-导航栏的高度 let navbarHeight = DOMUtils.height($mNavBar); let bottomTabTop = $bottomTab.getBoundingClientRect().top; if (bottomTabTop < navbarHeight) { // 超出上方|被覆盖在导航栏下面了 // 固定底部的tab if ($bottomTabVAffix.hasAttribute("data-is-fixed")) { } else { $bottomTabVAffix.style.cssText = `position: fixed;left: 0px;top: ${navbarHeight}px;z-index: 10000;width: 100%;`; $bottomTabVAffix.setAttribute("data-is-fixed", "true"); } } else { // 还在显示区域|在导航栏下面 // 取消固定tab $bottomTabVAffix.style.cssText = ""; $bottomTabVAffix.removeAttribute("data-is-fixed"); } }, { passive: true, } ); }, /** * 禁止滑动切换tab */ disableSwipeTab() { log.info(`禁止滑动切换tab`); VueUtils.waitVuePropToSet(".m-video-bottom-tab", { msg: "等待tab的vue属性touchstart、touchmove、touchend事件,_bindEvents函数", check(vueInstance) { return ( vueInstance?.slider?.el instanceof HTMLElement && typeof vueInstance?.slider?.events?.touchstart === "function" && typeof vueInstance?.slider?.events?.touchmove === "function" && typeof vueInstance?.slider?.events?.touchend === "function" && typeof vueInstance?.slider?._bindEvents === "function" ); }, set(vueInstance) { /** 绑定函数的目标元素 */ let $bindTarget = vueInstance.slider.el; $bindTarget.removeEventListener("touchstart", vueInstance.slider.events.touchstart); $bindTarget.removeEventListener("touchmove", vueInstance.slider.events.touchmove); $bindTarget.removeEventListener("touchend", vueInstance.slider.events.touchend); vueInstance.slider._bindEvents = () => {}; log.success(`成功禁用滑动,清除touchstart、touchmove、touchend事件,覆盖_bindEvents函数`); }, }); }, /** * 新增评论模块 */ addCommentModule() { log.info(`新增评论模块`); if (!this.$data.isInitCommentModule) { this.$data.isInitCommentModule = true; CommonUtil.setGMResourceCSS(GM_RESOURCE_MAPPING.Viewer); addStyle(MobileCommentModuleStyle); addStyle(/*css*/ ` .comment-container{ position: relative; } .comment-container .reply-header{ position: sticky; top: 0; z-index: 999; left: 0; right: 0; background: #fff; } #comment-module-wrapper{ position: fixed; top: 0; left: 0; z-index: 2000; display: none; width: 100vw; height: 100vh; background-color: #fff; overflow-x: hidden; } .close-comment-module-btn{ position: fixed; right: 20px; bottom: 20px; z-index: 2001; display: none; justify-content: center; align-items: center; width: 40px; height: 40px; color: #fff; border-radius: 100%; background-color: var(--bili-color); } `); addStyle(/*css*/ ` .comment-module-show-btn{ display: flex; justify-content: center; align-items: center; margin: 0 12px 20px 12px; height: 40px; color: #fff; border-radius: 4px; background-color: var(--bili-color); } `); } DOMUtils.waitNode(".m-video-info", 10000).then(($videoInfo) => { if (!$videoInfo) { log.error(`获取视频信息元素失败`); return; } // 移除旧的 DOMUtils.remove(".comment-module-show-btn"); DOMUtils.remove(".close-comment-module-btn"); DOMUtils.remove("#comment-module-wrapper"); const history_hash = "comment-module"; // 手势模式 let gestureBack = new GestureBack({ hash: history_hash, useUrl: true, beforeHistoryBackCallBack(isUrlChange) { let $viewerClose = $(".viewer-button.viewer-close"); // 当前是看图模式,仅退出看图 if ($viewerClose) { $viewerClose.click(); } if (isUrlChange) { $closeCommentModuleBtn.click(); } }, }); let $commentModuleShowBtn = DOMUtils.createElement("div", { className: "comment-module-show-btn", innerHTML: `查看评论`, }); let $closeCommentModuleBtn = DOMUtils.createElement("span", { className: "close-comment-module-btn", innerHTML: "×", }); // 显示评论模块 DOMUtils.on($commentModuleShowBtn, "click", (event) => { DOMUtils.preventEvent(event); DOMUtils.css($commentModuleWrapper, { display: "block" }); DOMUtils.css($closeCommentModuleBtn, { display: "flex" }); gestureBack.enterGestureBackMode(); }); // 隐藏评论模块 DOMUtils.on($closeCommentModuleBtn, "click", (event) => { DOMUtils.preventEvent(event); DOMUtils.css($commentModuleWrapper, { display: "" }); DOMUtils.css($closeCommentModuleBtn, { display: "" }); gestureBack.quitGestureBackMode(false); }); DOMUtils.append($videoInfo, $commentModuleShowBtn); let $commentModuleWrapper = DOMUtils.createElement("div", { id: "comment-module-wrapper", }); DOMUtils.append(document.body, $commentModuleWrapper); DOMUtils.after($commentModuleWrapper, $closeCommentModuleBtn); // 初始化评论模块 MobileCommentModule.init($commentModuleWrapper); }); }, /** * 新增简介模块 */ addDescModule() { log.info(`新增简介模块`); if (!this.$data.isInitDescModule) { this.$data.isInitDescModule = true; addStyle(/*css*/ ` ${BilibiliData.className.mVideo} .m-video-info .bottom-wrapper{ flex-direction: column; align-items: flex-start; height: auto; } `); addStyle(/*css*/ ` .video-desc-wrapper { color: #9499A0; font-size: 14px; width: 100%; .video-desc-text { margin: 10px 0px; white-space: pre-wrap; } .video-view-info-wrapper { display: flex; align-items: center; justify-content: flex-start; gap: 10px; margin: 5px 0px; .video-info-icon{ display: flex; align-items: center; gap: 2px; } .video-info-text{ display: flex; align-items: center; line-height: 1rem; } } .video-desc-controls-wrapper{ margin: 10px 0px; display: flex; justify-content: space-around; align-items: center; .video-info-icon { display: flex; flex-direction: column; align-items: center; gap: 2px; } } } `); } // 移除旧的 DOMUtils.remove(BilibiliData.className.mVideo + " .m-video-info .video-desc-wrapper"); VueUtils.waitVuePropToSet(BilibiliData.className.mVideo + " .m-video-info .bottom-wrapper", { check(vueInstance) { return typeof vueInstance?.info?.bvid === "string"; }, set(vueInstance, target) { // 视频信息 let info = vueInstance.info; // 视频作者信息 let upInfo = vueInstance.upInfo; // 粉丝数 let follower = upInfo.follower; // 投稿数 let archive_count = upInfo.archive_count; // 观看人数 let view = info.stat.view; // 弹幕数 let danmakuCount = info.stat.danmaku; // 发布时间 let ctime = info.ctime; // bv号 let bvid = info.bvid; // 视频描述 let desc = info.desc; // 点赞 let like = info.stat.like; // 投币 let coin = info.stat.coin; // 收藏 let favorite = info.stat.favorite; // 分享 let share = info.stat.share; let $descWrapper = DOMUtils.createElement("div", { className: "video-desc-wrapper", innerHTML: /*html*/ `
${BilibiliUtils.parseCount(view)}
${BilibiliUtils.parseCount(danmakuCount)}
${utils.formatTime(info.ctime * 1000, "yyyy年MM月dd日 HH:mm:ss")}
${bvid}
${desc}
${BilibiliUtils.parseCount(like)}
${BilibiliUtils.parseCount(coin)}
${BilibiliUtils.parseCount(favorite)}
${BilibiliUtils.parseCount(share)}
`, }); target.appendChild($descWrapper); }, }); }, };