视频分区插件

可以通过关键字在b站主页添加一个自定义分区(默认分区为A-soul分区)

  1. // ==UserScript==
  2. // @name 视频分区插件
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.8
  5. // @description 可以通过关键字在b站主页添加一个自定义分区(默认分区为A-soul分区)
  6. // @author tuntun
  7. // @match https://www.bilibili.com/*
  8. // @icon https://i2.hdslb.com/bfs/face/48d65a10a2c643dddc4a51e0a60fae892393417a.jpg
  9. // @grant GM_addStyle
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15.  
  16. (function() {
  17. 'use strict';
  18. GM_addStyle(`
  19. @media (min-width: 1701px) and (max-width: 2559.9px) {
  20. .tuntun-grid {
  21. grid-template-columns: repeat(5,1fr);
  22. }
  23. }
  24. @media (min-width: 1367px) and (max-width: 1700.9px) {
  25. .tuntun-part {
  26. grid-column: span 5 !important;
  27. }
  28. .tuntun-card-body {
  29. grid-column: span 5 !important;
  30. grid-template-columns: repeat(5,1fr) !important;
  31. }
  32. .video-card-list.is-main .tuntun-card-body>*:nth-of-type(1n + 9) {
  33. display: block!important;
  34. }
  35. }
  36. @media (min-width: 1100px) and (max-width: 1366.9px) {
  37. .tuntun-part {
  38. grid-column: span 5 !important;
  39. }
  40. .tuntun-card-body {
  41. grid-column: span 5 !important;
  42. grid-template-columns: repeat(5,1fr) !important;
  43. }
  44. .video-card-list.is-main .tuntun-card-body>*:nth-of-type(1n + 9) {
  45. display: block!important;
  46. }
  47. }
  48. @media (max-width: 1099.9px) {
  49. .tuntun-part {
  50. grid-column: span 4 !important;
  51. }
  52. .tuntun-card-body {
  53. grid-column: span 4 !important;
  54. grid-template-columns: repeat(4,1fr) !important;
  55. }
  56. .video-card-list.is-main .tuntun-card-body>*:nth-of-type(7) {
  57. display: block!important;
  58. }
  59. .video-card-list.is-main .tuntun-card-body>*:nth-of-type(8) {
  60. display: block!important;
  61. }
  62. }
  63. .tuntun-setting-popover {
  64. width: 300px;
  65. // height: 200px;
  66. background-color: white;
  67. border-radius: 20px;
  68. position: absolute;
  69. left: -120px;
  70. top: 43px;
  71. box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
  72. transition: opacity 0.5s, height 0.25s;
  73. }
  74.  
  75. .tuntun-setting-none {
  76. opacity: 0;
  77. height: 0;
  78. overflow: hidden;
  79. }
  80.  
  81. .tuntun-setting-form {
  82. padding: 20px 15px;
  83. display: flex;
  84. flex-direction: column;
  85. justify-content: center;
  86. }
  87.  
  88. .tuntun-setting-btn {
  89. margin: 0 auto;
  90. width: 84px;
  91. height: 38px;
  92. background-color:#b8a6d9;
  93. border: none;
  94. border-radius:10px;
  95. display:inline-block;
  96. cursor:pointer;
  97. color:#ffffff;
  98. font-family:Arial;
  99. font-size:17px;
  100. text-decoration:none;
  101. text-shadow:0px 0px 0px #9752cc;
  102. }
  103. .tuntun-setting-btn:hover {
  104. background-color:#bc80ea;
  105. }
  106. .tuntun-setting-btn:active {
  107. position:relative;
  108. top:1px;
  109. }
  110.  
  111. .tuntun-setting-input {
  112. margin-bottom: 15px;
  113. display: flex;
  114. align-items: center;
  115. }
  116.  
  117. .tuntun-setting-input div {
  118. margin-right: 10px
  119. }
  120.  
  121. .tuntun-setting-input input,select{
  122. width: 200px;
  123. border: 1px solid #ccc;
  124. padding: 7px 0px;
  125. border-radius: 3px;
  126. padding-left: 5px;
  127. transition: border 0.25s
  128. }
  129.  
  130. .tuntun-setting-input input:focus{
  131. outline: none;
  132. border: 1px solid #B8A6D9;
  133. }
  134.  
  135. .tuntun-setting-input select:focus{
  136. outline: none;
  137. border: 1px solid #B8A6D9;
  138. }
  139. .tuntun-setting-imgRadius {
  140. padding-left: 0px !important;
  141. }
  142. `);
  143.  
  144. const getTemplete = (videoKey, imgUrl = '') => {
  145. return `
  146. <section class="bili-grid tuntun-grid">
  147. <div class="video-card-list is-main tuntun-part">
  148. <div class="area-header" style="z-index: 1000;">
  149. <div class="left tuntun-part-left">
  150. <a id="A-soul分区" class="the-world area-anchor" data-id="8"></a>
  151. <img class="icon tuntun-part-img" src="${imgUrl}"></img>
  152. <a
  153. class="title"
  154. href="https://search.bilibili.com/all?keyword=${videoKey}"
  155. target="_blank"
  156. >
  157. <span>${videoKey}分区</span>
  158. </a>
  159. </div>
  160. <div class="right" style="position: relative;">
  161. <div id="tuntun-setting" style="position: relative;">
  162. <button class="primary-btn roll-btn">
  163. <span>设置</span></button
  164. >
  165. <div
  166. class="tuntun-setting-popover tuntun-setting-none"
  167. >
  168. <form class="tuntun-setting-form">
  169. <div class="tuntun-setting-input">
  170. <div>分区名称:</div>
  171. <input type="text" name="name" />
  172. </div>
  173. <div class="tuntun-setting-input">
  174. <div>分区图片:</div>
  175. <input type="text" name="picUrl" />
  176. </div>
  177. <div class="tuntun-setting-input">
  178. <div>图片圆角:</div>
  179. <input class="tuntun-setting-imgRadius" type="range" min="0" max="50"/>
  180. </div>
  181. <div class="tuntun-setting-input">
  182. <div>时间范围:</div>
  183. <select name="timeRange" id="">
  184. <option value="7">一周之内</option>
  185. <option value="30" selected>一月之内</option>
  186. <option value="90">三个月之内</option>
  187. <option value="0">不限时间</option>
  188. </select>
  189. </div>
  190. <input class="tuntun-setting-btn" type="submit" value="确认" />
  191. </form>
  192. </div>
  193. </div>
  194. <button id="refreshVideo" class="primary-btn roll-btn">
  195. <svg style="transform: rotate(0deg)">
  196. <use xlink:href="#widget-roll"></use></svg><span>换一换</span></button
  197. >
  198. <a
  199. class="primary-btn see-more tuntun-see-more"
  200. href="https://search.bilibili.com/all?keyword=${videoKey}"
  201. target="_blank"
  202. ><span>查看更多</span><svg><use xlink:href="#widget-arrow"></use></svg></a>
  203. </div>
  204. </div>
  205. <div class="video-card-body tuntun-card-body">
  206. </div>
  207. </div>
  208.  
  209. <!--
  210. <aside>
  211. <div class="aside-wrap">
  212. <div class="aside-head">
  213. <div class="area-header">
  214. <div class="left">
  215. <a
  216. class="title rank-title"
  217. href="https://www.bilibili.com/v/virtual"
  218. target="_blank"
  219. ><span>排行榜</span></a>
  220. </div>
  221. <div class="right">
  222. <a
  223. class="primary-btn see-more"
  224. href="https://www.bilibili.com/v/virtual"
  225. target="_blank"
  226. ><span>更多</span><svg><use xlink:href="#widget-arrow"></use></svg></a>
  227. </div>
  228. </div>
  229. </div>
  230. </div>
  231. </aside>
  232. -->
  233. </section>
  234. `;
  235. };
  236.  
  237. let asideBody = `
  238. <div class="aside-body">
  239. <div class="aside-core">
  240. <div class="bili-rank-list-video bili-rank-list-video__grid">
  241. <ul class="bili-rank-list-video__list video-rank-list">
  242. <li class="bili-rank-list-video__item">
  243. <div class="bili-rank-list-video__item--wrap">
  244. <span class="bili-rank-list-video__item--index" data-index="1"
  245. >1</span
  246. ><a
  247. href="//www.bilibili.com/video/BV1Hi4y1R7gy"
  248. class="rank-video-card"
  249. target="_blank"
  250. data-mod="partition_rank"
  251. data-idx="content"
  252. data-ext="click"
  253. ><div class="rank-video-card__image">
  254. <picture class="v-img rank-video-card__cover"
  255. ><!---->
  256. <source
  257. srcset="
  258. //i2.hdslb.com/bfs/archive/c92ce434742fb724af5577de2485a1eaff8aa226.jpg@192w_108h_1c_100q.webp
  259. "
  260. type="image/webp" />
  261. <img
  262. src="//i2.hdslb.com/bfs/archive/c92ce434742fb724af5577de2485a1eaff8aa226.jpg@192w_108h_1c_100q"
  263. alt="B站以前的LV6 VS 现在的LV6 2.0"
  264. loading="lazy"
  265. onload=""
  266. /></picture>
  267. </div>
  268. <div class="rank-video-card__info">
  269. <h3
  270. class="rank-video-card__info--tit"
  271. title="B站以前的LV6 VS 现在的LV6 2.0"
  272. >
  273. B站以前的LV6 VS 现在的LV6 2.0
  274. </h3>
  275. </div></a
  276. >
  277. </div>
  278. </li>
  279. <li class="bili-rank-list-video__item">
  280. <div class="bili-rank-list-video__item--wrap">
  281. <span class="bili-rank-list-video__item--index" data-index="2"
  282. >2</span
  283. ><a
  284. href="//www.bilibili.com/video/BV1Rb4y1Y7Pw"
  285. class="rank-video-card rank-video-card__concise"
  286. target="_blank"
  287. data-mod="partition_rank"
  288. data-idx="content"
  289. data-ext="click"
  290. ><!---->
  291. <div class="rank-video-card__info">
  292. <h3
  293. class="rank-video-card__info--tit"
  294. title="【自制动画】《鬼灭之刃》无限城篇(香奈乎单挑童磨 片段)"
  295. >
  296. 【自制动画】《鬼灭之刃》无限城篇(香奈乎单挑童磨 片段)
  297. </h3>
  298. </div></a
  299. >
  300. </div>
  301. </li>
  302. <li class="bili-rank-list-video__item">
  303. <div class="bili-rank-list-video__item--wrap">
  304. <span class="bili-rank-list-video__item--index" data-index="3"
  305. >3</span
  306. ><a
  307. href="//www.bilibili.com/video/BV1Z44y177Wt"
  308. class="rank-video-card rank-video-card__concise"
  309. target="_blank"
  310. data-mod="partition_rank"
  311. data-idx="content"
  312. data-ext="click"
  313. ><!---->
  314. <div class="rank-video-card__info">
  315. <h3
  316. class="rank-video-card__info--tit"
  317. title="小伙买了80个模型,爆肝一周,只为在家建造一个迷你世界"
  318. >
  319. 小伙买了80个模型,爆肝一周,只为在家建造一个迷你世界
  320. </h3>
  321. </div></a
  322. >
  323. </div>
  324. </li>
  325. <li class="bili-rank-list-video__item">
  326. <div class="bili-rank-list-video__item--wrap">
  327. <span class="bili-rank-list-video__item--index" data-index="4"
  328. >4</span
  329. ><a
  330. href="//www.bilibili.com/video/BV1mi4y1R7rT"
  331. class="rank-video-card rank-video-card__concise"
  332. target="_blank"
  333. data-mod="partition_rank"
  334. data-idx="content"
  335. data-ext="click"
  336. ><!---->
  337. <div class="rank-video-card__info">
  338. <h3
  339. class="rank-video-card__info--tit"
  340. title="准备好了么?来点刺激的!!!【嘉然】"
  341. >
  342. 准备好了么?来点刺激的!!!【嘉然】
  343. </h3>
  344. </div></a
  345. >
  346. </div>
  347. </li>
  348. <li class="bili-rank-list-video__item">
  349. <div class="bili-rank-list-video__item--wrap">
  350. <span class="bili-rank-list-video__item--index" data-index="5"
  351. >5</span
  352. ><a
  353. href="//www.bilibili.com/video/BV1VD4y1c788"
  354. class="rank-video-card rank-video-card__concise"
  355. target="_blank"
  356. data-mod="partition_rank"
  357. data-idx="content"
  358. data-ext="click"
  359. ><!---->
  360. <div class="rank-video-card__info">
  361. <h3
  362. class="rank-video-card__info--tit"
  363. title="顶上海鲜战争12分钟总集篇"
  364. >
  365. 顶上海鲜战争12分钟总集篇
  366. </h3>
  367. </div></a
  368. >
  369. </div>
  370. <!---->
  371. </li>
  372. <li class="bili-rank-list-video__item">
  373. <div class="bili-rank-list-video__item--wrap">
  374. <span class="bili-rank-list-video__item--index" data-index="6"
  375. >6</span
  376. ><a
  377. href="//www.bilibili.com/video/BV14r4y1S71X"
  378. class="rank-video-card rank-video-card__concise"
  379. target="_blank"
  380. data-mod="partition_rank"
  381. data-idx="content"
  382. data-ext="click"
  383. ><!---->
  384. <div class="rank-video-card__info">
  385. <h3
  386. class="rank-video-card__info--tit"
  387. title="【原神手书】荒泷一斗 【Misfit Lunatic】"
  388. >
  389. 【原神手书】荒泷一斗 Misfit Lunatic
  390. </h3>
  391. </div></a
  392. >
  393. </div>
  394. <!---->
  395. </li>
  396. <li class="bili-rank-list-video__item">
  397. <div class="bili-rank-list-video__item--wrap">
  398. <span class="bili-rank-list-video__item--index" data-index="7"
  399. >7</span
  400. ><a
  401. href="//www.bilibili.com/video/BV1jL411L7Vm"
  402. class="rank-video-card rank-video-card__concise"
  403. target="_blank"
  404. data-mod="partition_rank"
  405. data-idx="content"
  406. data-ext="click"
  407. ><!---->
  408. <div class="rank-video-card__info">
  409. <h3
  410. class="rank-video-card__info--tit"
  411. title="【平成三萌】摇起来迎接2022~~~~~~"
  412. >
  413. 【平成三萌】摇起来迎接2022~~~~~~
  414. </h3>
  415. </div></a
  416. >
  417. </div>
  418. <!---->
  419. </li>
  420. <li class="bili-rank-list-video__item">
  421. <div class="bili-rank-list-video__item--wrap">
  422. <span class="bili-rank-list-video__item--index" data-index="8"
  423. >8</span
  424. ><a
  425. href="//www.bilibili.com/video/BV1tY411p7G5"
  426. class="rank-video-card rank-video-card__concise"
  427. target="_blank"
  428. data-mod="partition_rank"
  429. data-idx="content"
  430. data-ext="click"
  431. ><!---->
  432. <div class="rank-video-card__info">
  433. <h3
  434. class="rank-video-card__info--tit"
  435. title="你瞧瞧现在哪儿有萌新啊"
  436. >
  437. 你瞧瞧现在哪儿有萌新啊
  438. </h3>
  439. </div></a
  440. >
  441. </div>
  442. <!---->
  443. </li>
  444. <li class="bili-rank-list-video__item">
  445. <div class="bili-rank-list-video__item--wrap">
  446. <span class="bili-rank-list-video__item--index" data-index="9"
  447. >9</span
  448. ><a
  449. href="//www.bilibili.com/video/BV1ji4y1R7LL"
  450. class="rank-video-card rank-video-card__concise"
  451. target="_blank"
  452. data-mod="partition_rank"
  453. data-idx="content"
  454. data-ext="click"
  455. ><!---->
  456. <div class="rank-video-card__info">
  457. <h3
  458. class="rank-video-card__info--tit"
  459. title="女生想让男朋友知道的事有哪些?"
  460. >
  461. 女生想让男朋友知道的事有哪些?
  462. </h3>
  463. </div></a
  464. >
  465. </div>
  466. <!---->
  467. </li>
  468. <li class="bili-rank-list-video__item">
  469. <div class="bili-rank-list-video__item--wrap">
  470. <span
  471. class="bili-rank-list-video__item--index"
  472. data-index="10"
  473. >10</span
  474. ><a
  475. href="//www.bilibili.com/video/BV12L4y1E7G2"
  476. class="rank-video-card rank-video-card__concise"
  477. target="_blank"
  478. data-mod="partition_rank"
  479. data-idx="content"
  480. data-ext="click"
  481. ><!---->
  482. <div class="rank-video-card__info">
  483. <h3
  484. class="rank-video-card__info--tit"
  485. title="看到朋友脱单我比si了还难受"
  486. >
  487. 看到朋友脱单我比si了还难受
  488. </h3>
  489. </div></a
  490. >
  491. </div>
  492. <!---->
  493. </li>
  494. </ul>
  495. </div>
  496. <!----><!---->
  497. </div>
  498. </div>`
  499.  
  500. const Tool = {
  501. // 大数转万
  502. formatBigNumber: (num) => {
  503. return num > 10000 ? `${(num / 10000).toFixed(2)}万` : num
  504. },
  505. // 字符串转DOM
  506. s2d: (string) => {
  507. return new DOMParser().parseFromString(string, 'text/html').body
  508. .childNodes[0]
  509. },
  510. // 发布时间格式化
  511. diffTime: (time) => {
  512. let upDate = new Date(parseInt(time, 10) * 1000);
  513. let nowDate = new Date();
  514. let nowTime = nowDate.getTime(),
  515. upTime = upDate.getTime(),
  516. Day = 24 * 60 * 60 * 1000,
  517. Hours = 60 * 60 * 1000,
  518. Minutes = 60 * 1000,
  519. diffDay = parseInt((nowTime - upTime) / Day),
  520. diffHours = parseInt((nowTime - upTime) / Hours),
  521. diffMinutes = Math.floor((nowTime - upTime) / Minutes);
  522. if(diffDay != 0 && diffDay < 7) {
  523. if ( diffDay === 1 ) {
  524. return '昨天'
  525. }
  526. return diffDay + '天前';
  527. }
  528. else if(diffDay === 0 && diffHours != 0) {
  529. return diffHours + '小时前';
  530. }
  531. else if(diffDay === 0 && diffHours === 0 && diffMinutes != 0) {
  532. return diffMinutes + '分钟前';
  533. }
  534. else if (diffDay === 0 && diffHours === 0 && diffMinutes === 0) {
  535. return '刚刚';
  536. }
  537. else {
  538. let month = upDate.getMonth() + 1;
  539. let day = upDate.getDate();
  540. if (nowDate.getFullYear() !== upDate.getFullYear()) {
  541. return `${upDate.getFullYear()}-${month < 10 ? 0 : ''}${month}-${day < 10 ? 0 : ''}${day}`
  542. }
  543. return `${month < 10 ? 0 : ''}${month}-${day < 10 ? 0 : ''}${day}`
  544. }
  545. },
  546. // 判断发布时间与现在时间是否过长
  547. isTimeTooLate: (time, rangeDay = 30) => {
  548. let day = parseInt(rangeDay, 10);
  549. if (day === 0) {
  550. return false;
  551. }
  552. let upData = new Date(parseInt(time, 10) * 1000);
  553. let nowTime = new Date().getTime(),
  554. upTime = upData.getTime(),
  555. Day = 24 * 60 * 60 * 1000,
  556. diffDay = parseInt((nowTime - upTime) / Day);
  557. if (diffDay > day) {
  558. return true;
  559. }
  560. return false;
  561. }
  562. }
  563.  
  564. const API = {
  565. // 封装get方法
  566. Get: async (props) => {
  567. const { url: baseUrl, params = {} } = props;
  568. let pStr = Object.keys(params).map((key) => {
  569. return `${key}=${params[key]}`;
  570. }).join('&');
  571. let url = `${baseUrl}${pStr !== '' ? '?' : ''}${pStr}`;
  572. try {
  573. let res = await fetch(url, {
  574. credentials: "include"
  575. });
  576. return (await res.json()).data;
  577. } catch (error) {
  578. console.error('Get Error', error);
  579. }
  580. },
  581. // 通过关键词获取视频数据
  582. getVideo: async (keyWord, page = 1) => {
  583. try {
  584. let res = await API.Get({
  585. url: 'https://api.bilibili.com/x/web-interface/search/type',
  586. params: {
  587. search_type: 'video',
  588. keyword: keyWord,
  589. page: page,
  590. }
  591. });
  592. return res.result;
  593. } catch (error) {
  594. console.log('getVideo', error);
  595. }
  596. },
  597. }
  598. let videoList = [];
  599. let page = 1;
  600. let searchPage = 1;
  601. let bvList = [];
  602. let pageSize = 10;
  603. let videoKey = GM_getValue('videoKey', 'A-soul');
  604. let rangeDay = GM_getValue('rangeDay', '30');
  605. let imgBorderRadius = GM_getValue('imgBorderRadius', '15');
  606. let defaultImgUrl = 'https://i2.hdslb.com/bfs/face/48d65a10a2c643dddc4a51e0a60fae892393417a.jpg';
  607. let imgUrl = GM_getValue('imgUrl', defaultImgUrl);
  608.  
  609. // 获取数据并渲染
  610. const getVideoCardTemplete = (data) => {
  611. let videoCardBody = document.querySelector('.video-card-body');
  612. videoCardBody.innerHTML = '';
  613. data.forEach((item, index) => {
  614. if (index < pageSize) {
  615. const {
  616. bvid, pic, mid,
  617. upic, author, play,
  618. like, duration, pubdate } = item;
  619. let title = item.title.replace(/<em class="keyword">(.*?)<\/em>/g, '$1');
  620. // let domStr = `
  621. // <div class="bili-video-card">
  622. // <div class="bili-video-card__skeleton hide">
  623. // <div class="bili-video-card__skeleton--cover"></div>
  624. // <div class="bili-video-card__skeleton--info">
  625. // <div class="bili-video-card__skeleton--face"></div>
  626. // <div class="bili-video-card__skeleton--right">
  627. // <p class="bili-video-card__skeleton--text"></p>
  628. // <p class="bili-video-card__skeleton--text short"></p>
  629. // <p class="bili-video-card__skeleton--light"></p>
  630. // </div>
  631. // </div>
  632. // </div>
  633. // <div class="bili-video-card__wrap __scale-wrap">
  634. // <a
  635. // href="//www.bilibili.com/video/${bvid}"
  636. // target="_blank"
  637. // data-mod="partition_recommend"
  638. // data-idx="content"
  639. // data-ext="click"
  640. // ><div class="bili-video-card__image __scale-player-wrap">
  641. // <div class="bili-video-card__image--wrap">
  642. // <div class="bili-watch-later" style="display: none">
  643. // <svg class="bili-watch-later__icon">
  644. // <use xlink:href="#widget-watch-later"></use></svg><span
  645. // class="bili-watch-later__tip"
  646. // style="display: none"
  647. // ></span>
  648. // </div>
  649. // <picture class="v-img bili-video-card__cover"
  650. // ><!---->
  651. // <source
  652. // srcset="
  653. // ${pic}@672w_378h_1c_100q.webp
  654. // "
  655. // type="image/webp" />
  656. // <img
  657. // src="${pic}@672w_378h_1c_100q"
  658. // alt="${title}"
  659. // loading="lazy"
  660. // onload=""
  661. // /></picture>
  662. // <div class="v-inline-player"></div>
  663. // </div>
  664. // <div class="bili-video-card__mask">
  665. // <div class="bili-video-card__stats">
  666. // <div class="bili-video-card__stats--left">
  667. // <span class="bili-video-card__stats--item"
  668. // ><svg class="bili-video-card__stats--icon">
  669. // <use xlink:href="#widget-play-count"></use></svg><span class="bili-video-card__stats--text"
  670. // >${Tool.formatBigNumber(play)}</span
  671. // ></span
  672. // ><span class="bili-video-card__stats--item"
  673. // ><svg class="bili-video-card__stats--icon">
  674. // <use xlink:href="#widget-agree"></use></svg><span class="bili-video-card__stats--text"
  675. // >${Tool.formatBigNumber(like)}</span
  676. // ></span
  677. // >
  678. // </div>
  679. // <span class="bili-video-card__stats__duration">${duration}</span>
  680. // </div>
  681. // </div>
  682. // </div></a
  683. // >
  684. // <div class="bili-video-card__info __scale-disable">
  685. // <a
  686. // href="//space.bilibili.com/${mid}"
  687. // target="_blank"
  688. // data-mod="partition_recommend"
  689. // data-idx="content"
  690. // data-ext="click"
  691. // ><div class="v-avatar bili-video-card__avatar">
  692. // <picture class="v-img v-avatar__face"
  693. // ><!---->
  694. // <source
  695. // srcset="
  696. // ${upic.substr(5)}@72w_72h.webp
  697. // "
  698. // type="image/webp" />
  699. // <img
  700. // src="${upic.substr(5)}@72w_72h"
  701. // alt="${author}"
  702. // loading="lazy"
  703. // onload="" /></picture
  704. // ><!---->
  705. // </div></a
  706. // >
  707. // <div class="bili-video-card__info--right">
  708. // <a
  709. // href="//www.bilibili.com/video/${bvid}"
  710. // target="_blank"
  711. // data-mod="partition_recommend"
  712. // data-idx="content"
  713. // data-ext="click"
  714. // ><h3
  715. // class="bili-video-card__info--tit"
  716. // title="${title}"
  717. // >
  718. // ${title}
  719. // </h3></a
  720. // >
  721. // <p class="bili-video-card__info--bottom">
  722. // <a
  723. // class="bili-video-card__info--owner"
  724. // href="//space.bilibili.com/${mid}"
  725. // target="_blank"
  726. // data-mod="partition_recommend"
  727. // data-idx="content"
  728. // data-ext="click"
  729. // ><span class="bili-video-card__info--author">${author}</span
  730. // ><span class="bili-video-card__info--date"
  731. // >· ${Tool.diffTime(pubdate)}</span
  732. // ></a
  733. // >
  734. // </p>
  735. // </div>
  736. // </div>
  737. // </div>
  738. // </div>
  739. // `;
  740. let domStr = `
  741. <div class="bili-video-card" data-report="partition_recommend.content">
  742. <div class="bili-video-card__skeleton hide">
  743. <div class="bili-video-card__skeleton--cover"></div>
  744. <div class="bili-video-card__skeleton--info">
  745. <div class="bili-video-card__skeleton--face"></div>
  746. <div class="bili-video-card__skeleton--right">
  747. <p class="bili-video-card__skeleton--text"></p>
  748. <p class="bili-video-card__skeleton--text short"></p>
  749. <p class="bili-video-card__skeleton--light"></p>
  750. </div>
  751. </div>
  752. </div>
  753. <div class="bili-video-card__wrap __scale-wrap"><a href="//www.bilibili.com/video/${bvid}" target="_blank"
  754. data-mod="partition_recommend" data-idx="content" data-ext="click">
  755. <div class="bili-video-card__image __scale-player-wrap">
  756. <div class="bili-video-card__image--wrap">
  757. <div class="bili-watch-later" style="display: none;"><svg class="bili-watch-later__icon">
  758. <use xlink:href="#widget-watch-later"></use>
  759. </svg><span class="bili-watch-later__tip" style="display: none;"></span></div>
  760. <picture class="v-img bili-video-card__cover">
  761. <!---->
  762. <source srcset="${pic}@672w_378h_1c.webp"
  763. type="image/webp"><img
  764. src="${pic}@672w_378h_1c"
  765. alt="${title}" loading="lazy" onload="">
  766. </picture>
  767. <div class="v-inline-player"></div>
  768. </div>
  769. <div class="bili-video-card__mask">
  770. <div class="bili-video-card__stats">
  771. <div class="bili-video-card__stats--left"><span class="bili-video-card__stats--item"><svg
  772. class="bili-video-card__stats--icon">
  773. <use xlink:href="#widget-play-count"></use>
  774. </svg><span class="bili-video-card__stats--text">${Tool.formatBigNumber(play)}</span></span><span
  775. class="bili-video-card__stats--item"><svg class="bili-video-card__stats--icon">
  776. <use xlink:href="#widget-agree"></use>
  777. </svg><span class="bili-video-card__stats--text">${Tool.formatBigNumber(like)}</span></span></div><span
  778. class="bili-video-card__stats__duration">${duration}</span>
  779. </div>
  780. </div>
  781. </div>
  782. </a>
  783. <div class="bili-video-card__info __scale-disable">
  784. <!---->
  785. <div class="bili-video-card__info--right"><a
  786. href="https://www.bilibili.com/video/${bvid}"
  787. target="_blank" data-mod="partition_recommend" data-idx="content" data-ext="click">
  788. <h3 class="bili-video-card__info--tit" title="${title}">${title}</h3>
  789. </a>
  790. <p class="bili-video-card__info--bottom">
  791. <!----><a class="bili-video-card__info--owner" href="//space.bilibili.com/${mid}" target="_blank"
  792. data-mod="partition_recommend" data-idx="content" data-ext="click"><svg
  793. class="bili-video-card__info--owner__up">
  794. <use xlink:href="#widget-up"></use>
  795. </svg><span class="bili-video-card__info--author">${author}</span><span class="bili-video-card__info--date"
  796. ${Tool.diffTime(pubdate)}</span></a>
  797. </p>
  798. </div>
  799. </div>
  800. </div>
  801. </div>
  802. `;
  803. videoCardBody.appendChild(Tool.s2d(domStr));
  804. }
  805. });
  806. };
  807.  
  808. // 更新视频
  809. const refreshVideo = async () => {
  810. let firstVideoIndex = (page - 1) * pageSize;
  811. let lastVideoIndex = firstVideoIndex + pageSize - 1;
  812. while(videoList.length < lastVideoIndex + 1) {
  813. let data = await API.getVideo(videoKey, searchPage);
  814. data.forEach((item) => {
  815. if (!Tool.isTimeTooLate(item.pubdate, rangeDay)) {
  816. if (bvList.indexOf(item.bvid) === -1) {
  817. videoList.push(item);
  818. bvList.push(item.bvid);
  819. }
  820. }
  821. });
  822. searchPage++;
  823. };
  824. page++;
  825. let applyData = videoList.slice(firstVideoIndex, lastVideoIndex + 1)
  826. getVideoCardTemplete(applyData);
  827. };
  828.  
  829. // 填入框架
  830. let main = document.querySelector('.bili-layout');
  831. let gridAll = document.querySelectorAll('.bili-grid');
  832. if (main !== null) {
  833. let templete = getTemplete(videoKey, imgUrl);
  834. main.insertBefore(Tool.s2d(templete), gridAll[2]);
  835.  
  836. // 第一次获取数据并渲染
  837. const applyFirstData = async () => {
  838. refreshVideo();
  839. };
  840. applyFirstData();
  841. // 换一换按钮添加更新视频事件
  842. let refreshVideoBtn = document.querySelector('#refreshVideo');
  843. refreshVideoBtn.addEventListener('click', refreshVideo);
  844.  
  845. // popover
  846. const showpopover = (x, y) => {
  847. return `
  848. <div id="asoul-popover" style="position: absolute; z-index: 2000; top: ${y}px; left: ${x}px;">
  849. <div class="v-popover is-top" style="padding-bottom: 0px; margin-left: 0px; pointer-events: none;">
  850. <div class="v-popover-content bili-rank-list-video">
  851. <div class="rank-video-card__popover">
  852. <div class="rank-video-card__popover--top">
  853. <div class="rank-video-card__image rank-video-card__popover--image">
  854. <picture class="v-img rank-video-card__cover rank-video-card__popover--cover">
  855. <!---->
  856. <source srcset="//i1.hdslb.com/bfs/archive/6ac4c468f90987ecd2a51f1753f7d043560ac271.jpg@192w_108h.webp"
  857. type="image/webp"><img
  858. src="//i1.hdslb.com/bfs/archive/6ac4c468f90987ecd2a51f1753f7d043560ac271.jpg@192w_108h"
  859. alt="小伙买了80个模型,爆肝一周,只为在家建造一个迷你世界" loading="lazy" onload="">
  860. </picture>
  861. </div>
  862. <div class="rank-video-card__info rank-video-card__popover--info">
  863. <h3 class="rank-video-card__popover--tit" title="小伙买了80个模型,爆肝一周,只为在家建造一个迷你世界">小伙买了80个模型,爆肝一周,只为在家建造一个迷你世界
  864. </h3>
  865. <p class="rank-video-card__popover--author"><span>拜托了小翔哥</span><span> · 12-29</span></p>
  866. </div>
  867. </div>
  868. <ul class="rank-video-card__popover--stats">
  869. <li class="rank-video-card__popover--stats__item"><svg class="rank-video-card__popover--icon">
  870. <use xlink:href="#widget-play-count"></use>
  871. </svg><span>93万</span></li>
  872. <li class="rank-video-card__popover--stats__item"><svg class="rank-video-card__popover--icon">
  873. <use xlink:href="#widget-danmaku"></use>
  874. </svg><span>3931</span></li>
  875. <li class="rank-video-card__popover--stats__item"><svg class="rank-video-card__popover--icon">
  876. <use xlink:href="#widget-favorite"></use>
  877. </svg><span>1.3万</span></li>
  878. <li class="rank-video-card__popover--stats__item"><svg class="rank-video-card__popover--icon">
  879. <use xlink:href="#widget-coin"></use>
  880. </svg><span>7.6万</span></li>
  881. </ul>
  882. </div>
  883. </div>
  884. </div>
  885. </div>
  886. `
  887. }
  888.  
  889. // 侧边
  890. // let aside = document.querySelector('.aside-wrap');
  891. // aside.append(Tool.s2d(asideBody));
  892.  
  893. let setting = document.querySelector('#tuntun-setting');
  894. let settingBtn = setting.children[0];
  895. let settingPop = setting.children[1];
  896. let settingForm = settingPop.children[0];
  897. let partNameInput = settingForm.children[0].children[1];
  898. let partImgUrlInput = settingForm.children[1].children[1];
  899. let partImgDom = document.querySelector('.tuntun-part-img');
  900. partImgDom.style.borderRadius = `${imgBorderRadius}%`;
  901. let radiusRangeInput = document.querySelector('.tuntun-setting-imgRadius');
  902. let partTimeRangeInput = settingForm.children[3].children[1];
  903.  
  904. // 设置按钮点击事件
  905. settingBtn.addEventListener('click', () => {
  906. if (settingPop.className === 'tuntun-setting-popover tuntun-setting-none') {
  907. settingPop.className = 'tuntun-setting-popover';
  908. } else {
  909. settingPop.className = 'tuntun-setting-popover tuntun-setting-none';
  910. }
  911. partNameInput.value = videoKey;
  912. partImgUrlInput.value = imgUrl;
  913. partTimeRangeInput.value = rangeDay;
  914. radiusRangeInput.value = imgBorderRadius;
  915. partImgDom.style.borderRadius = `${imgBorderRadius}%`;
  916. });
  917.  
  918. // videoKey改变
  919. const videoKeyChange = (newKey) => {
  920. let seeMoreBtn = document.querySelector('.tuntun-see-more');
  921. let headerLeft = document.querySelector('.tuntun-part-left');
  922. videoKey = newKey;
  923. videoList = [];
  924. page = 1;
  925. searchPage = 1;
  926. bvList = [];
  927. GM_setValue('videoKey', newKey);
  928. seeMoreBtn.href = `https://search.bilibili.com/all?keyword=${newKey}`;
  929. headerLeft.children[2].href = `https://search.bilibili.com/all?keyword=${newKey}`;
  930. headerLeft.children[2].children[0].innerHTML = `${newKey}分区`;
  931. refreshVideo();
  932. }
  933.  
  934. // imgUrl改变
  935. const imgUrlChange = (newUrl) => {
  936. let partImgDom = document.querySelector('.tuntun-part-img');
  937. imgUrl = newUrl;
  938. GM_setValue('imgUrl', newUrl);
  939. partImgDom.src = newUrl;
  940. }
  941.  
  942. // 设置img的圆角
  943. radiusRangeInput.addEventListener('change', () => {
  944. partImgDom.style.borderRadius = `${radiusRangeInput.value}%`;
  945. });
  946. const imgBorderRadiusChange = (newRadiusNum) => {
  947. imgBorderRadius = newRadiusNum;
  948. GM_setValue('imgBorderRadius', newRadiusNum);
  949. }
  950.  
  951. // 时间范围改变
  952. const timeRangeChange = (timeRange) => {
  953. rangeDay = timeRange;
  954. videoList = [];
  955. page = 1;
  956. searchPage = 1;
  957. bvList = [];
  958. GM_setValue('rangeDay', timeRange);
  959. refreshVideo();
  960. }
  961.  
  962. // 设置表单确认
  963. settingForm.addEventListener('submit', (e) => {
  964. e.preventDefault();
  965. if (partNameInput.value !== videoKey) {
  966. videoKeyChange(partNameInput.value);
  967. }
  968. if (partImgUrlInput.value !== imgUrl) {
  969. imgUrlChange(partImgUrlInput.value);
  970. }
  971. if (radiusRangeInput.value !== imgBorderRadius) {
  972. imgBorderRadiusChange(radiusRangeInput.value);
  973. }
  974. if (partTimeRangeInput.value !== rangeDay) {
  975. timeRangeChange(partTimeRangeInput.value);
  976. }
  977. settingPop.className = 'tuntun-setting-popover tuntun-setting-none';
  978. });
  979. }
  980. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址