Greasy Fork is available in English.

奇讯影视解析 (2025最新优化版) - 悬浮面板 - 多源同时解析

优酷、爱奇艺、腾讯、B站等视频网站VIP视频解析,悬浮面板,多源解析(可选6/4/1个源),单源放大并替换

  1. // ==UserScript==
  2. // @name 奇讯影视解析 (2025最新优化版) - 悬浮面板 - 多源同时解析
  3. // @namespace qx-vip-video
  4. // @version 1.7.5
  5. // @description 优酷、爱奇艺、腾讯、B站等视频网站VIP视频解析,悬浮面板,多源解析(可选6/4/1个源),单源放大并替换
  6. // @author xnone
  7. // @icon data:image/webp;base64,UklGRoYNAABXRUJQVlA4WAoAAAAgAAAAewEAewEASUNDUBgCAAAAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANlZQOCBICwAAUF4AnQEqfAF8AT7tdrZTqacrIqQxyZlgHYljbuFwgM8g360bIH7r+482/2DJyfyPo/7v1Ifqj9//eK9NXoN8wnm7acr/Jd6gyWz0j6SvH/SU1U76djv8jx0r5Fyh+Hsoh6v/8FoNBENstP/8U5oe605BODARorgyBFO7RYP4fsUEPM8Xlaiz6EhfBFeIQ/qGrijRXBkItS1+UUZY4gXvPdYkQqUjxiUUo0kojiqAkgxXT++7kqnGzSSkNNW3FSUEOGVcUaK4MhAdbT+2pHD7liULWIzQGhVxRorgyD+L/kwstYGw9Gh7Q4zws3Nk7iFLVoNbMVBQWnCLhlrfFL7Vs1A6e3czC9Vvw5OclLagRN2UAXx+ZOneU/vLQbchWIEGW5mJuXFOhnC/y1jSC2rwWsfMyHr/FAD/JTzgEhJ9l22iWzBdkjeaDsnHMw9IO+52YKnJ7hQL1JCnkmamOPRdw8fHASMF5HaUAB9qNAETNo5HsZ1d1BRo5RT86sEz6IAS7mFV7CVzH34LZcDAZJI83/H5k7eb/qsydUZ9QdcfCM6DelyonA2uSdxIUFWZO4ixKZOp1SXg1OHK2wLZKeew0kBN5JV9GmYXuxKhaXfqIfyMi+032kzf7sOj4IyQGUrmF5Fp2v0WVbZ2sxWQdTO9XxJzH3QdDayFyfSe37GiCSroSLV6Nc4IPRD8VMjsuio3NvKpPdf6lyEZ0G/wjT49Q+azG9FE/+KuiQbQuM7PKxc3KoLzHWzDzTl1vTl6JG/RHz6TyCEbl6MnjMTEdJmMlBDK4FHAU56BUZRe7EprrmBO6q7+9yBAfULbwFleuSgElaT+KSF+BcJtgv2Fvoof8/URlXFBsiYNKrRwB47bpXFGiudgvRucg/mtg2E+trYvrSX2fDRXBkIwfcUaKmjWOL3oP/I8oXGMlBC04TijRW6sPd2HEodzIaNeTkvBoSwiyoIWnCNv5BlQqLt/ThV1pQH4Db9qb6w19181OQiyn/Z+v8Y2ccMpLy2OAAD+/JxXwAxMptVkXenhMndiAPi1fjzAxJp6H0ZVhxgYiwCyKY6Eqydoui9XdgCwJKwiMfaQfttV2uGDuw5+Zi1H90oUl1UsN2gyKS6qX6t7nfh4phLuFfUhpotJsaFAhr5kkTS6JIJ/0dFUvMI9K8eQ5ZZVi/fb7KaSmNqh72DH60XyZTedrXw1UryVZ82JtIu8xGz0S0Rd2cxElNvVj0cxhLwckwNZS3B+o8xU32NSVyhBWvsXAAeuoE3jBOfV8oiKzjmnk7qOsUgtZ7yYEpWtehGbstXn/yrhuG/kdnFN0Njz9rwKecMay2mgABYAHcyB1d7O1Fciu5dWq27Oqp7EIMNuhSFAiDLw4JP4yS3TnSVpAd2AC38Rki6VFVGIYaXpg+YJEsH5aDhh2rkoepws8FHq7QUmHdVijNMdEk94zwtsZrgc5kgAAbWdZkWDL9u3Sa2DETj0caHJkzHfFGZXVOSlHSfQeqVHfRJABRwzSVrZpa4EAm/tKp5j2e+oI2MVNdqdrpikoQ9p1LO38DOyKLhHYy0NilfGAmfcUCKZcEqK/Bc53PGE+TfxeKu0bcGFA2SFIYg7qiMVBReLJmwMU4CrWIQ2jqlnmMfxcThW7LmLO25eTtuwzTqAJRF7Fk3YPQZ2/YiwajaQI/3jD/JrYn0d8Vve991lpfY6tlSaZwoGOphe3W1M7OJPzTJapumpOEszzXBIAHWo4x/9NIHh8S67fAqUT4vzs1STHWaXOD3CZcwBvSaJxa/c7+IXcKbA6k38EfycvmKSjeiUl5RUHaWKDrtUGbz6nq/pG8BNoFkqIUVCrrnxBkhm/9sP1+j6uvw8XmCbGQ/UosfZ2iCqdL4Uy1Uea9L9GLr8F9cYxpOzDhXgbUALKysYNv6xDTbRQPM/0yO1Hqgth28tzhLmakf+HKUk85sgvgqM1sI9hu3+HK+SZIo7QKpWYsr2aZUaLg6nsv7VTrrSQYdW6ZF3c2QWUlhrcPh28Qjnba3jfrKWCFitkMukmMQxc9dpCbFQPVDtlj5OjZA/5MULHYhZ5hpnw8lC3ehF98fM0SypMlQ9aWpvF4PhweSOmJH7wCCViHE2oxwZXJ0iN8cHbtHKl1owU/FXifAMJX2fTc1UnecehvAACGSK4R7LFiGnmS7zRvLOMVzMGG2M8jB40BawVbRSYwjLKGM5OPJ6VtbccXJwJPdme19aDGrbeSoAiXtz3L5CuLXadMJgOtTT4Qe7WtcVhBMefDsELIUDoWJGXwTATS/TJWazU/mKTD7P5ZXpKzo9QRkSXzSBLy11fwBtDqjy6F04BLtJquJ4ItTsZ1Hsk2IwYKDcBDvPd0+YSAs6ClgzciLq06zm5CIGPcBGZ0fZxrE+ENmVmrBomJI33at6wEnJTFJxz2NYTrBL/uwpA/gWgktHKqI7U2yKvlqtZvE3Uqi3JGoEbkBIY7mC0zVVH78IOGrmMA4nLYBa2leLYvuf7z454DE6dQTfkA0LCZp4/o1RK/b+Hffhs3axSMBU6QTbyxgH9dcXDRrty7Z6qDDTWdKXwdpN26U8YixzjGWz54v5Uvw6AeEzu78cWozysCHstH0sygCNngqrxtggzN52z3kRwBH8qFKIZ5F/G8ux87K5I9b/kzFtzIagMsfVLJozoCXpss0P1ZUpVSw/LLiOT0OQjKurq35xwXy5xaLkrNJJrGZlbXy6LkAaEnAL0sBANiUEgK5K0kuHufz+sFgu1R1+iUmxE/bi1YSu1oJPczINLzuJeQU0jjhq/HWVNZ0dNHO53kojAe5dApNlN+wviHKMYfA9N75QGbuuqDuZQUmJbyYEbn5jNJ4b6/3PJyFyeGvJDwnlup5gGqrbQH3+YO3FZuv/k/1lP4SiuyZAWKe+7rvQ3soTBrG9hYmWY2cjzpkRDXFAxPDkUKjOewUadQYoOkWecvryz3ByArdA+tI3rhjp9yGxYeSUZjf65qdCaVNhXZ73NzSEKqPicJ95lcnuLw8+7/J617iYrSLWCJlv48KI5YYYZwHYCGQTVxwyRV3VhubpClqWWRw4AfDol/NWrGERZAk+ShqPagD2tsW/iUhxv+KUWrHMOs+4GiGyf8uxQ7p7i24jDmlJeL8NpBabGaJbk7wY4E1jgam7BkwYJQ6LfyAPHPwwvRi5x6u05wH+3kfi5wL+yyiQYzv3OfPCxXZbFCzQBwGY12tdktBj2XzVBeZTJIwH4cFl3zRpC7IfT8vqNU/+puEOPR3Fx00ncTfkmIp40bLGdaG+9HGPVd+w6Xq4XP1CCaKFwH0LchYNKkZVRyLIhee9qTtn2aDU61Rlgc4taGSgWoAPytwfkwK/rW7Ac4IG95+9L5A1TyEitTzrb+0rBUT0obdJ6Z/O3mhuRqPrtXMZKVebTtlA24CK+UXmhRO3szJI+cHHcHLdT4dNbMvoeCX4tAZ6CIplACvUCDl37YiYm1iiZX8ETA4uZdt0xMnOlvarRmFFfTqLdvs4AAAMpkBGpSIgejvuVh+vGs3W3h33+Kv/Z4HZ/9c8UOhLZTHdHbePsKnYrhKpMSknAABFoU6uiSKea5SaBSU2Fmkyjc6J0fzph3Ivn8J60BnLFsoI3ueXSZeNpt3HDHgB8MpCdUJwQfcfkjHvCqogAHAWdfKRxCG/5MO1JXCsZPjPJFKSblq4ZYdAiaL9ZrwxXsmnW0XyeZcqK4qglTnu69BFDIavN3L1+oAlYy3uGZ79/vNXISJLxKGzfMuvZxkAHYhvLQSgDXRVpRsdpe6RGnqX/VwSwCaSwoEPsRFeEc8/fuZzmuiU9tbII6vPikHBEWexyIn5iyMFylJp0m+wAAA=
  8. // @match *://*.youku.com/*
  9. // @match *://*.iqiyi.com/*
  10. // @match *://*.iq.com/*
  11. // @match *://v.qq.com/*
  12. // @match *://*.bilibili.com/*
  13. // @match *://*.mgtv.com/*
  14. // @match *://*.le.com/*
  15. // @match *://*.tudou.com/*
  16. // @match *://*.pptv.com/*
  17. // @match *://*.1905.com/*
  18. // @grant GM_getValue
  19. // @grant GM_setValue
  20. // @grant GM_registerMenuCommand
  21. // @license GPLv3
  22. // ==/UserScript==
  23.  
  24. (function () {
  25. 'use strict';
  26.  
  27. const isMobile = /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent);
  28.  
  29. // 解析线路配置
  30. const parseUrls = [
  31. "https://jx.dmflv.cc/?url=",
  32. "https://www.yemu.xyz/?url=",
  33. "https://jx.nnxv.cn/tv.php?url=",
  34. "https://jx.playerjy.com/?ads=0&url=",
  35. "https://jx.xmflv.com/?url=",
  36. "https://videocdn.ihelpy.net/jiexi/m1907.html?m1907jx=",
  37.  
  38. // "https://im1907.top/?jx=",
  39. // "https://jx.jsonplayer.com/player/?url=",
  40. // "https://jx.yangtu.top/?url=",
  41. // "https://vip.bljiex.com/?v=",
  42. // "https://www.ckplayer.vip/jiexi/?url=",
  43. // "https://jx.m3u8.tv/jiexi/?url="
  44. ];
  45.  
  46. // 网站与解析规则的映射
  47. const siteRules = {
  48. 'v.qq.com': { node: ['.player__container', '#player-container'], area: 'playlist-list' },
  49. 'iqiyi.com': { node: ['#video'], area: '' },
  50. 'iq.com': { node: ['.intl-video-wrap'], area: 'm-sliding-list' },
  51. 'youku.com': { node: ['#ykPlayer'], area: 'new-box-anthology-items' },
  52. 'bilibili.com': { node: ['#bilibili-player', '.bpx-player-primary-area'], area: 'video-episode-card' },
  53. 'mgtv.com': { node: ['#mgtv-player-wrap'], area: 'episode-items' },
  54. 'le.com': { node: ['#le_playbox'], area: 'juji_grid' },
  55. 'tudou.com': { node: ['#player'], area: '' },
  56. 'pptv.com': { node: ['#pptv_playpage_box'], area: '' },
  57. '1905.com': { node: ['#player', '#vodPlayer'], area: '' },
  58. };
  59.  
  60. let originalVideoContainer = null;
  61. let originalVideoContainerSelector = null;
  62. let currentIframeContainer = null;
  63. let videoContainerWidth = null;
  64. let videoContainerHeight = null;
  65. let hidePanelTimeout = null; // 隐藏面板的定时器
  66.  
  67. function getSiteRule(host) {
  68. return siteRules[Object.keys(siteRules).find(key => host.includes(key))] || null;
  69. }
  70.  
  71. function createParseElements() {
  72. const iconSize = isMobile ? 40 : GM_getValue('iconWidth', 40);
  73. const iconTop = isMobile ? 360 : GM_getValue('iconTop', 360);
  74. const iconPosition = isMobile ? 'left' : GM_getValue('iconPosition', 'left');
  75.  
  76. const iconStyle = `
  77. #vipParseIcon {
  78. position: fixed;
  79. top: ${iconTop}px;
  80. ${iconPosition}: 5px;
  81. z-index: 999999;
  82. cursor: pointer;
  83. display: flex;
  84. flex-direction: ${iconPosition === 'left' ? 'row' : 'row-reverse'};
  85. }
  86. #vipParseIcon img {
  87. width: ${iconSize}px;
  88. height: ${iconSize * 1.5}px;
  89. opacity: ${isMobile ? 1 : GM_getValue('iconOpacity', 100) / 100};
  90. transition: transform 0.3s ease;
  91. }
  92. #vipParseIcon:hover img {
  93. transform: scale(1.2);
  94. }
  95.  
  96. #parsePanel {
  97. position: absolute; /* 绝对定位 */
  98. top: ${iconSize * 1.5}px; /* 图标高度+5px的间距*/
  99. ${iconPosition === 'left' ? 'left: 0;' : 'right: 0;'} /* 根据图标位置调整 */
  100. z-index: 999998;
  101. background-color: #fff;
  102. border: 1px solid #ccc;
  103. padding: 15px;
  104. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  105. border-radius: 5px;
  106. width: 280px; /* 调整面板宽度 */
  107. display: none; /* 初始隐藏 */
  108. }
  109.  
  110. #parsePanel button {
  111. margin: 8px 0;
  112. padding: 10px 18px;
  113. background-color: #2871a6;
  114. color: #fff;
  115. border: none;
  116. border-radius: 4px;
  117. cursor: pointer;
  118. transition: background-color 0.3s;
  119. width: 100%;
  120. box-sizing: border-box;
  121. }
  122. #parsePanel button:hover {
  123. background-color: #1e5a88;
  124. }
  125.  
  126. #parsePanel .warning-tips {
  127. background: #ffeeee; /* 红色背景 */
  128. color: #ff0000; /* 红色字体 */
  129. padding: 15px; /* 内边距 */
  130. border-radius: 5px; /* 圆角 */
  131. box-shadow: 0 0 10px rgba(0,0,0,0.1); /* 投影效果 */
  132. z-index: 1000; /* 确保提示显示在最前面 */
  133. font-size: 12px; /* 字体大小 */
  134. line-height: 1.5; /* 行间距 */
  135. }
  136. #parsePanel .warning-tips p {
  137. margin: 5px 0; /* 段落间距 */
  138. }
  139.  
  140. #configPanel {
  141. margin-top: 15px;
  142. padding-top: 10px;
  143. border-top: 1px solid #eee;
  144. }
  145.  
  146. #configPanel label {
  147. display: block;
  148. margin-bottom: 8px;
  149. color: #333;
  150. }
  151. #configPanel input[type="radio"] {
  152. margin-right: 6px;
  153. }
  154.  
  155. #saveConfigBtn {
  156. background-color: #4CAF50 !important;
  157. }
  158. #saveConfigBtn:hover {
  159. background-color: #45a049 !important;
  160. }
  161.  
  162. #aboutPanel {
  163. margin-top: 15px;
  164. padding: 15px;
  165. background-color: #f8f9fa;
  166. border-radius: 4px;
  167. }
  168.  
  169. #aboutPanel h3 {
  170. margin-top: 0;
  171. color: #2c3e50;
  172. }
  173.  
  174. #aboutPanel p {
  175. color: #34495e;
  176. line-height: 1.6;
  177. }
  178.  
  179. #telegramLink {
  180. color: #007bff;
  181. text-decoration: underline;
  182. cursor: pointer;
  183. }
  184.  
  185. /* ... 其他样式保持不变 ... */
  186. .iframe-container {
  187. display: grid;
  188. grid-template-columns: repeat(3, 1fr);
  189. grid-template-rows: repeat(2, auto);
  190. grid-auto-rows: minmax(200px, auto);
  191. grid-gap: 1px;
  192. width: 100%;
  193. height: 100%;
  194. }
  195. .iframe-container iframe {
  196. width: 100%;
  197. height: 100%;
  198. border: 1px solid #ddd;
  199. }
  200. /* 可选:添加响应式设计 */
  201. @media (max-width: 768px) {
  202. .iframe-container {
  203. grid-template-columns: repeat(2, 1fr); /* 在小屏幕上显示两列 */
  204. }
  205. }
  206.  
  207. @media (max-width: 480px) {
  208. .iframe-container {
  209. grid-template-columns: 1fr; /* 在非常小的屏幕上显示一列 */
  210. }
  211. }
  212.  
  213. .iframe-wrapper {
  214. position: relative;
  215. }
  216.  
  217. .expand-button {
  218. position: absolute;
  219. bottom: 0;
  220. left: 0;
  221. width: 100%;
  222. background-color: rgba(0, 0, 0, 0.5);
  223. color: white;
  224. text-align: center;
  225. padding: 5px 0;
  226. cursor: pointer;
  227. opacity: 0;
  228. transition: opacity 0.3s;
  229. }
  230. .iframe-wrapper:hover .expand-button {
  231. opacity: 1;
  232. }
  233. `;
  234.  
  235. const styleEl = document.createElement('style');
  236. styleEl.textContent = iconStyle;
  237. document.head.appendChild(styleEl);
  238.  
  239. const iconHtml = `
  240. <img src="data:image/webp;base64,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" />
  241. <div id="parsePanel">
  242. <div>
  243. <button id="parseBtn">👉解析</button>
  244. <button id="gotoSiteBtn" style="background:#5a6268;">去奇讯边聊边看</button>
  245. <button id="restoreBtn" style="background:#5a6268;">还原</button>
  246. </div>
  247. <div id="configPanel">
  248. <label><input type="radio" name="iframeCount" value="6"> 6个格子解析</label>
  249. <label><input type="radio" name="iframeCount" value="4"> 4个格子解析</label>
  250. <label><input type="radio" name="iframeCount" value="1"> 1个格子解析</label>
  251. <button id="saveConfigBtn">保存配置</button>
  252. <div id="configTips" style="margin-top: 10px; padding: 5px 10px; color: red; display: none;font-size:12px;">配置已保存并生效!</div>
  253. </div>
  254. <div class="warning-tips">
  255. <p>⚠️ 注意:</p>
  256. <p>如果全部解析失败请过段时间再试</p>
  257. <p>请勿相信视频中的任何广告,都是假的</p>
  258. </div>
  259.  
  260. <div id="aboutPanel">
  261. <h3>🎥 奇讯视频解析工具</h3>
  262. <p>一键解析多平台视频,支持多源选择,提供便捷的观看体验。</p>
  263. <a id="telegramLink" href="https://t.me/qixunyingshi" target="_blank">点击加入 Telegram 群组</a>
  264. </div>
  265. </div>
  266. `;
  267.  
  268.  
  269. const container = document.createElement('div');
  270. container.id = 'vipParseIcon';
  271. container.innerHTML = iconHtml;
  272. document.body.appendChild(container);
  273.  
  274. const parsePanel = document.getElementById('parsePanel');
  275. const vipParseIcon = document.getElementById('vipParseIcon');
  276. const parseBtn = document.getElementById('parseBtn');
  277. const configPanel = document.getElementById('configPanel');
  278. const saveConfigBtn = document.getElementById('saveConfigBtn');
  279. const restoreBtn = document.getElementById('restoreBtn');
  280. const gotoSiteBtn = document.getElementById('gotoSiteBtn');
  281. const icon = container.querySelector('img');
  282. const telegramLink = document.getElementById('telegramLink');
  283.  
  284. // 初始化配置
  285. const iframeCount = GM_getValue('iframeCount', '6');
  286. configPanel.querySelector(`input[value="${iframeCount}"]`).checked = true;
  287.  
  288. // 鼠标移入图标:显示面板,清除隐藏定时器
  289. icon.addEventListener('mouseover', () => {
  290. clearTimeout(hidePanelTimeout);
  291. parsePanel.style.display = 'block';
  292. });
  293.  
  294. // 鼠标移出图标:启动隐藏面板定时器
  295. icon.addEventListener('mouseleave', () => {
  296. hidePanelTimeout = setTimeout(() => {
  297. parsePanel.style.display = 'none';
  298. }, 300);
  299. });
  300.  
  301. // 鼠标移入面板:清除隐藏定时器
  302. parsePanel.addEventListener('mouseover', () => {
  303. clearTimeout(hidePanelTimeout);
  304. });
  305.  
  306. // 鼠标移出面板:启动隐藏面板定时器
  307. parsePanel.addEventListener('mouseleave', () => {
  308. hidePanelTimeout = setTimeout(() => {
  309. parsePanel.style.display = 'none';
  310. }, 300);
  311. });
  312.  
  313. // 保存配置
  314. saveConfigBtn.addEventListener('click', () => {
  315. const newIframeCount = configPanel.querySelector('input[name="iframeCount"]:checked').value;
  316. GM_setValue('iframeCount', newIframeCount);
  317. if (originalVideoContainer) {
  318. parseVideoMulti();
  319. }
  320. // 获取提示元素
  321. const tips = document.getElementById('configTips');
  322. tips.style.display = 'block';
  323. // 3秒后隐藏
  324. setTimeout(() => {
  325. tips.style.display = 'none';
  326. }, 3000);
  327. });
  328.  
  329. parsePanel.addEventListener('click', (e) => {
  330. e.stopPropagation()
  331. });
  332. parseBtn.addEventListener('click', parseVideoMulti);
  333. vipParseIcon.addEventListener('click', parseVideoMulti);
  334. restoreBtn.addEventListener('click', restoreVideo);
  335. gotoSiteBtn.addEventListener('click', () => window.open(`https://qx.bluu.pl/#/?url=${encodeURIComponent(location.href)}`, '_blank'));
  336. telegramLink.addEventListener('click', (e) => {
  337. e.stopPropagation();
  338. window.open('https://t.me/qixunyingshi', '_blank');
  339. });
  340.  
  341. makeDraggable(container, icon);
  342. }
  343.  
  344. function getVideoContainer() {
  345. const siteRule = getSiteRule(location.hostname);
  346. if (!siteRule) {
  347. console.log('未找到匹配的网站规则');
  348. return null;
  349. }
  350. let videoContainer = null;
  351. for (const node of siteRule.node) {
  352. videoContainer = document.querySelector(node);
  353. if (videoContainer) {
  354. originalVideoContainerSelector = node;
  355. videoContainerWidth = videoContainer.offsetWidth;
  356. videoContainerHeight = videoContainer.offsetHeight;
  357. break;
  358. }
  359. }
  360. return videoContainer;
  361. }
  362.  
  363. function expandAndReplaceIframe(iframe) {
  364. const videoContainer = getVideoContainer();
  365. if (!videoContainer) return;
  366.  
  367. const newIframe = document.createElement('iframe');
  368. newIframe.src = iframe.src;
  369. newIframe.allowFullscreen = iframe.allowFullscreen;
  370. newIframe.allowTransparency = iframe.allowTransparency;
  371.  
  372. newIframe.style.width = videoContainerWidth + 'px';
  373. newIframe.style.height = videoContainerHeight + 'px';
  374. newIframe.style.border = 'none';
  375.  
  376. videoContainer.innerHTML = '';
  377. videoContainer.appendChild(newIframe);
  378. currentIframeContainer = null;
  379. }
  380.  
  381. function parseVideoMulti() {
  382. const videoContainer = getVideoContainer();
  383. if (!videoContainer) return;
  384.  
  385. if (!originalVideoContainer) {
  386. originalVideoContainer = videoContainer.innerHTML;
  387. }
  388.  
  389. const iframeCount = parseInt(GM_getValue('iframeCount', '6'));
  390. const urls = parseUrls.slice(0, iframeCount);
  391.  
  392. let gridColumns = 1;
  393. if (iframeCount === 6) {
  394. gridColumns = 3;
  395. } else if (iframeCount === 4) {
  396. gridColumns = 2;
  397. }
  398.  
  399. let iframeHTML = `<div class="iframe-container" style="grid-template-columns: repeat(${gridColumns}, 1fr);">`;
  400. urls.forEach(url => {
  401. iframeHTML += `
  402. <div class="iframe-wrapper">
  403. <iframe src="${url}${encodeURIComponent(location.href)}" allowfullscreen allowtransparency></iframe>
  404. <div class="expand-button">⬆️用这个视频继续播放</div>
  405. </div>
  406. `;
  407. });
  408. iframeHTML += '</div>';
  409.  
  410. videoContainer.innerHTML = iframeHTML;
  411. currentIframeContainer = videoContainer.querySelector('.iframe-container');
  412.  
  413. const expandButtons = videoContainer.querySelectorAll('.expand-button');
  414. expandButtons.forEach((button, index) => {
  415. button.addEventListener('click', () => {
  416. expandAndReplaceIframe(videoContainer.querySelectorAll('iframe')[index]);
  417. });
  418. });
  419.  
  420. const siteRule = getSiteRule(location.hostname);
  421. if (siteRule && siteRule.area) {
  422. const areaSelector = `.${siteRule.area}`;
  423. if (!videoContainer.dataset.eventBound) {
  424. const bindAreaEvent = () => {
  425. const areaElement = document.querySelector(areaSelector);
  426. if (areaElement) {
  427. areaElement.addEventListener('click', () => {
  428. setTimeout(parseVideoMulti, 1000); // 延时并重新解析
  429. });
  430. videoContainer.dataset.eventBound = 'true';
  431. }
  432. };
  433. bindAreaEvent();
  434. const observer = new MutationObserver(bindAreaEvent);
  435. observer.observe(document.body, { childList: true, subtree: true });
  436. }
  437. }
  438. }
  439.  
  440. function restoreVideo() {
  441. if (!originalVideoContainer) return;
  442. const videoContainer = document.querySelector(originalVideoContainerSelector);
  443. if (videoContainer) {
  444. videoContainer.innerHTML = originalVideoContainer;
  445. currentIframeContainer = null;
  446. } else {
  447. console.error("找不到原始视频容器:", originalVideoContainerSelector);
  448. }
  449. }
  450.  
  451. function makeDraggable(element, handle) {
  452. let isDragging = false;
  453. let startX, startY, startTop;
  454.  
  455. handle.addEventListener('mousedown', (e) => {
  456. e.preventDefault();
  457. if (e.button !== 0) return;
  458.  
  459. isDragging = true;
  460. startX = e.clientX;
  461. startY = e.clientY;
  462. startTop = element.offsetTop;
  463.  
  464. document.addEventListener('mousemove', onMouseMove);
  465. document.addEventListener('mouseup', onMouseUp);
  466. });
  467.  
  468. function onMouseMove(e) {
  469. if (!isDragging) return;
  470.  
  471. const deltaY = e.clientY - startY;
  472. let newTop = startTop + deltaY;
  473. const maxHeight = window.innerHeight - element.offsetHeight - 10;
  474. newTop = Math.max(0, Math.min(newTop, maxHeight));
  475. element.style.top = `${newTop}px`;
  476. }
  477.  
  478. function onMouseUp() {
  479. isDragging = false;
  480. document.removeEventListener('mousemove', onMouseMove);
  481. document.removeEventListener('mouseup', onMouseUp);
  482. GM_setValue('iconTop', element.offsetTop);
  483. }
  484. }
  485.  
  486. window.addEventListener('load', () => {
  487. if (getSiteRule(location.hostname)) {
  488. createParseElements();
  489.  
  490. const siteRule = getSiteRule(location.hostname);
  491. if (siteRule && siteRule.area) {
  492. const areaSelector = `.${siteRule.area}`;
  493. const videoContainer = getVideoContainer();
  494. if (videoContainer && !videoContainer.dataset.eventBound) {
  495. const bindAreaEvent = () => {
  496. const areaElement = document.querySelector(areaSelector);
  497. if (areaElement) {
  498. areaElement.addEventListener('click', () => {
  499. setTimeout(parseVideoMulti, 1000);
  500. });
  501. videoContainer.dataset.eventBound = 'true';
  502. }
  503. };
  504.  
  505. bindAreaEvent();
  506. const observer = new MutationObserver(bindAreaEvent);
  507. observer.observe(document.body, { childList: true, subtree: true });
  508. }
  509. }
  510. }
  511. });
  512.  
  513. GM_registerMenuCommand("设置解析线路", () => {
  514. const selectedLine = prompt("请选择或输入解析线路的URL:", localStorage.getItem('preferredParseLine') || parseUrls[0]);
  515. if (selectedLine) {
  516. localStorage.setItem('preferredParseLine', selectedLine);
  517. location.reload();
  518. }
  519. });
  520. })();