AcWing Better++

在AcWing Better!的基础上支持多设备同时登录(不可用)功能(改自北极小狐的AcWing Better!)

  1. // ==UserScript==
  2. // @name AcWing Better++
  3. // @version 3.29.1
  4. // @description 在AcWing Better!的基础上支持多设备同时登录(不可用)功能(改自北极小狐的AcWing Better!)
  5. // @author CN059
  6. // @match https://www.acwing.com/*
  7. // @icon https://aowuucdn.oss-cn-beijing.aliyuncs.com/acwing.png
  8. // @grant GM_xmlhttpRequest
  9. // @grant GM_info
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_addStyle
  13. // @grant GM_setClipboard
  14. // @connect sustech.edu.cn
  15. // @run-at document-end
  16. // @require https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/turndown/7.2.0/turndown.min.js#sha512-sJzEecN5Nk8cq81zKtGq6/z9Z/r3q38zV9enY75IVxiG7ybtlNUt864sL4L1Kf36bYIwxTMVKQOtU4VhD7hGrw==
  17. // @license MIT
  18. // @namespace https://gf.qytechs.cn/zh-CN/users/1426478
  19. // ==/UserScript==
  20.  
  21. // 状态与初始化
  22. const getGMValue = (key, defaultValue) => {
  23. const value = GM_getValue(key);
  24. if (value === undefined) {
  25. GM_setValue(key, defaultValue);
  26. return defaultValue;
  27. }
  28. return value;
  29. };
  30. const { hostname, href } = window.location;
  31. const bottomBar = getGMValue("bottomBar", true);
  32. const bingWallpaper = getGMValue("bingWallpaper", true);
  33. const widthAdjustment = getGMValue("widthAdjustment", true);
  34. const autoPlay = getGMValue("autoPlay", true);
  35. const acTimer = getGMValue("acTimer", true);
  36. const hideNavbar = getGMValue("hideNavbar", false);
  37. const sessionId = getGMValue("sessionId", "");
  38.  
  39. // 检查用户是否登录(不可用)
  40. function checkLoginStatus() {
  41. // 检查是否有登录(不可用)/注册(不可用)按钮
  42. const hasLoginButton = document.querySelector('a[href="#"][data-toggle="modal"][data-target="#login-modal"]') !== null;
  43. return !hasLoginButton; // 如果有登录(不可用)按钮,表示未登录(不可用)
  44. }
  45.  
  46. // 检查sessionId是否存在和登录(不可用)状态
  47. function checkSessionAndLogin() {
  48. const isLoggedIn = checkLoginStatus();
  49. const hasSessionId = document.cookie.includes('sessionid=');
  50.  
  51. if (!isLoggedIn || !hasSessionId) {
  52. showSessionNotification("您的账号信息已过期,请在设置中更新sessionId", "error");
  53. }
  54. }
  55.  
  56. // 设置cookie
  57. function setCookie(name, value, days) {
  58. let expires = "";
  59. if (days) {
  60. const date = new Date();
  61. date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
  62. expires = "; expires=" + date.toUTCString();
  63. }
  64. document.cookie = name + "=" + (value || "") + expires + "; path=/; domain=" + window.location.hostname;
  65. }
  66.  
  67. // 获取cookie
  68. function getCookie(name) {
  69. const cookies = document.cookie.split(";");
  70. for (let i = 0; i < cookies.length; i++) {
  71. const cookie = cookies[i].trim();
  72. const [cookieName, cookieValue] = cookie.split("=");
  73.  
  74. if (cookieName === name) {
  75. return decodeURIComponent(cookieValue);
  76. }
  77. }
  78. return "";
  79. }
  80.  
  81. // 显示通知
  82. function showSessionNotification(message, type) {
  83. // 防止重复显示通知
  84. if (document.getElementById('acwing-session-notification')) {
  85. return;
  86. }
  87.  
  88. const notification = document.createElement('div');
  89. notification.id = 'acwing-session-notification';
  90. notification.style.position = 'fixed';
  91. notification.style.top = '20px';
  92. notification.style.right = '20px';
  93. notification.style.padding = '15px 20px';
  94. notification.style.backgroundColor = type === 'error' ? '#ffebee' : '#e8f5e9';
  95. notification.style.color = type === 'error' ? '#c62828' : '#2e7d32';
  96. notification.style.border = type === 'error' ? '1px solid #ef9a9a' : '1px solid #a5d6a7';
  97. notification.style.borderRadius = '4px';
  98. notification.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
  99. notification.style.zIndex = '99999';
  100. notification.style.display = 'flex';
  101. notification.style.alignItems = 'center';
  102. notification.style.justifyContent = 'space-between';
  103. notification.style.maxWidth = '300px';
  104. notification.innerHTML = `
  105. <span>${message}</span>
  106. <svg style="margin-left: 10px; cursor: pointer;" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  107. <line x1="18" y1="6" x2="6" y2="18"></line>
  108. <line x1="6" y1="6" x2="18" y2="18"></line>
  109. </svg>
  110. `;
  111.  
  112. const closeBtn = notification.querySelector('svg');
  113. closeBtn.addEventListener('click', () => {
  114. notification.style.display = 'none';
  115. });
  116.  
  117. document.body.appendChild(notification);
  118.  
  119. setTimeout(() => {
  120. notification.style.transition = 'opacity 0.5s';
  121. notification.style.opacity = '0';
  122. setTimeout(() => {
  123. notification.remove();
  124. }, 500);
  125. }, 5000);
  126. }
  127.  
  128. // 常量
  129. const helpCircleHTML = '<div class="help-icon"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm23.744 191.488c-52.096 0-92.928 14.784-123.2 44.352-30.976 29.568-45.76 70.4-45.76 122.496h80.256c0-29.568 5.632-52.8 17.6-68.992 13.376-19.712 35.2-28.864 66.176-28.864 23.936 0 42.944 6.336 56.32 19.712 12.672 13.376 19.712 31.68 19.712 54.912 0 17.6-6.336 34.496-19.008 49.984l-8.448 9.856c-45.76 40.832-73.216 70.4-82.368 89.408-9.856 19.008-14.08 42.24-14.08 68.992v9.856h80.96v-9.856c0-16.896 3.52-31.68 10.56-45.76 6.336-12.672 15.488-24.64 28.16-35.2 33.792-29.568 54.208-48.576 60.544-55.616 16.896-22.528 26.048-51.392 26.048-86.592 0-42.944-14.08-76.736-42.24-101.376-28.16-25.344-65.472-37.312-111.232-37.312zm-12.672 406.208a54.272 54.272 0 0 0-38.72 14.784 49.408 49.408 0 0 0-15.488 38.016c0 15.488 4.928 28.16 15.488 38.016A54.848 54.848 0 0 0 523.072 768c15.488 0 28.16-4.928 38.72-14.784a51.52 51.52 0 0 0 16.192-38.72 51.968 51.968 0 0 0-15.488-38.016 55.936 55.936 0 0 0-39.424-14.784z"></path></svg></div>';
  130. const darkenPageStyle = `body::before { content: ""; display: block; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.4); z-index: 9999; }`;
  131.  
  132. // 样式
  133. if (bottomBar) {
  134. GM_addStyle(`
  135. .fs-gui-taskbar {
  136. height: 3.5vh !important;
  137. background-color: #dde1e5 !important;
  138. }
  139. .fs-gui-taskbar-widgets-apps-item > img {
  140. height: 2.2vh !important;
  141. width: 2.2vh !important;
  142. margin: 0.5vh 0.5vh 0.5vh 0.5vh !important;
  143. }
  144. .fs-gui-taskbar-widgets-clock{
  145. width: 0px !important;
  146. height: 0px !important;
  147. overflow: hidden !important;
  148. }
  149. .fs-gui-taskbar-widgets-apps-item {
  150. margin-right: 2vh !important;
  151. }
  152. #fs-gui-taskbar-search-field {
  153. font-size: 13px !important;
  154. }
  155. .fs-gui-taskbar-search-icon {
  156. font-size: 16px !important;
  157. top: 0.95vh !important;
  158. left: 4.3vh !important;
  159. }
  160. .fs-gui-taskbar-begin {
  161. height: 3vh !important;
  162. width: 3vh !important;
  163. margin: 0.2vh !important;
  164. border-radius: 60%;
  165. background-color: #fffefe80 !important;
  166. }
  167. button.fs-gui-taskbar-begin.pull-left.btn.btn-default img {
  168. width: 83% !important;
  169. }
  170. #fs-gui-taskbar-search-field {
  171. height: 90% !important;
  172. margin: 0.15vh;
  173. border-radius: 100px;
  174. border-width: 0.2vh;
  175. border-style: solid;
  176. border-color: #c7d2dd;
  177. }
  178. #fs-gui-taskbar-search-field:focus-visible {
  179. border-width: 0.2vh;
  180. border-style: solid;
  181. border-color: #8bb2d9;
  182. outline: -webkit-focus-ring-color auto 0px;
  183. }
  184. `);
  185. }
  186. if (bingWallpaper) {
  187. GM_addStyle(`
  188. #acwing_body {
  189. background: white url(https://bingw.jasonzeng.dev) fixed !important;
  190. }
  191. `);
  192. }
  193. if (widthAdjustment) {
  194. GM_addStyle(`
  195. .container {
  196. width: auto !important;
  197. margin: 0px 3px;
  198. }
  199. `);
  200. $(document).ready(function () {
  201. $('.base_body .container .row').children().removeClass(' col-sm-offset-2 col-sm-8 col-md-offset-2 col-md-9');
  202. $('.col-md-8').removeClass('col-md-8').addClass('col-md-12');
  203. })
  204. }
  205. GM_addStyle(`
  206. span.mdViewContent {
  207. white-space: pre-wrap;
  208. }
  209. .file-explorer-main-field-item.file-explorer-main-field-item-desktop {
  210. width: 0px;
  211. height: 0px;
  212. overflow: hidden;
  213. }
  214. .comment-conent {
  215. overflow-x: auto;
  216. }
  217. /* 页脚 */
  218. footer#acwing_footer .copyright {
  219. color: #fff;
  220. }
  221. footer#acwing_footer .copyright a, .links a, footer#acwing_footer .container {
  222. color: #fff;
  223. }
  224. /* 复制按钮 */
  225. pre.hljs {
  226. display: flex;
  227. justify-content: space-between;
  228. }
  229. span.copy-button {
  230. cursor: pointer;
  231. background-color: #e6e6e6;
  232. color: #727378;
  233. height: 20px;
  234. font-size: 13px;
  235. border-radius: 0.3rem;
  236. padding: 1px 5px;
  237. margin: 5px;
  238. box-shadow: 0 0 1px #0000004d;
  239. }
  240. span.copy-button.copied {
  241. background-color: #07e65196;
  242. color: #104f2b;
  243. }
  244. /* html2md */
  245. .html2md-panel {
  246. display: flex;
  247. justify-content: flex-end;
  248. }
  249. button.html2mdButton {
  250. height: 30px;
  251. width: 30px;
  252. }
  253. button.html2mdButton {
  254. display: flex;
  255. align-items: center;
  256. cursor: pointer;
  257. background-color: #ffffff;
  258. color: #606266;
  259. height: 22px;
  260. width: auto;
  261. font-size: 13px;
  262. border-radius: 0.3rem;
  263. padding: 1px 5px;
  264. margin: 5px;
  265. border: 1px solid #dcdfe6;
  266. }
  267. button.html2mdButton:hover {
  268. color: #409eff;
  269. border-color: #409eff;
  270. background-color: #f1f8ff;
  271. }
  272. button.html2mdButton.copied {
  273. background-color: #f0f9eb;
  274. color: #67c23e;
  275. border: 1px solid #b3e19d;
  276. }
  277. button.html2mdButton.html2md-view.mdViewed {
  278. background-color: #ff980057;
  279. color: #5a3a0c;
  280. }
  281. /* 打卡框 */
  282. .ui.bottom.attached.tab.segment.active {
  283. padding: 0px;
  284. }
  285. /* 视频bar */
  286. .embed-responsive {
  287. height: max-content;
  288. padding-bottom: 0px;
  289. }
  290. .player_bar {
  291. margin: 2px;
  292. display: flex;
  293. justify-content: space-between;
  294. }
  295. .player_bar_go {
  296. cursor: pointer;
  297. width: 50px;
  298. color: #999;
  299. height: auto;
  300. font-size: 13px;
  301. border-radius: 0.3rem;
  302. padding: 1px 5px;
  303. margin: 5px;
  304. border: none;
  305. background: linear-gradient(-225deg,#d5dbe4,#f8f8f8);
  306. box-shadow: inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);
  307. display: flex;
  308. justify-content: center;
  309. align-items: center;
  310. }
  311. button#player_bar_list_add_new_item_btn {
  312. height: 30px;
  313. width: 50px;
  314. background-color: #00aeec;
  315. color: #ffffff;
  316. font-size: 13px;
  317. border-radius: 0rem 0.5rem 0.5rem 0rem;
  318. padding: 1px 5px;
  319. margin: 5px 5px 5px 0px;
  320. border: none;
  321. box-shadow: 0 0 1px #0000004d;
  322. }
  323. div#player_bar_list {
  324. display: grid;
  325. width: 100%;
  326. border-radius: 0.3rem 0rem 0rem 0.3rem;
  327. margin: 5px 0px 5px 0px;
  328. border: 1px solid #00aeeccc;
  329. }
  330. div#player_bar_list input[type="radio"] {
  331. appearance: none;
  332. width: 0;
  333. height: 0;
  334. overflow: hidden;
  335. }
  336. div#player_bar_list input[type=radio]:focus {
  337. outline: 0px;
  338. }
  339. label.player_bar_ul_li_text {
  340. max-width: 100%;
  341. height: 90px;
  342. overflow-x: auto;
  343. font-weight: 400;
  344. margin: 0px 4px;
  345. border: 1px dashed #0000004d;
  346. padding: 3px;
  347. }
  348. ul#player_bar_ul li button {
  349. background-color: #e6e6e6;
  350. color: #727378;
  351. height: 23px;
  352. font-size: 14px;
  353. border-radius: 0.3rem;
  354. padding: 1px 5px;
  355. margin: 5px;
  356. border: none;
  357. box-shadow: 0 0 1px #0000004d;
  358. }
  359. ul#player_bar_ul {
  360. list-style-type: none;
  361. padding-inline-start: 0px;
  362. display: flex;
  363. overflow-x: auto;
  364. max-width: 100%;
  365. margin: 0px;
  366. }
  367. ul#player_bar_ul li {
  368. height: 100px;
  369. width: 80px;
  370. display: grid;
  371. overflow: hidden;
  372. margin: 4px 4px;
  373. min-width: 100px;
  374. }
  375. label.player_bar_ul_li_text:hover {
  376. background-color: #eae4dc24;
  377. }
  378. input[type="radio"]:checked + .player_bar_ul_li_text {
  379. background: #41e49930;
  380. border: 1px solid green;
  381. color: green;
  382. }
  383.  
  384. ul#player_bar_ul::-webkit-scrollbar {
  385. width: 5px;
  386. height: 8px;
  387. }
  388. ul#player_bar_ul::-webkit-scrollbar-thumb {
  389. border-radius: 2px;
  390. border: 1px solid rgba(56,56,56,.3411764706);
  391. background-clip: padding-box;
  392. background-color: #a29bb84a;
  393. background-image: -webkit-linear-gradient(45deg,hsla(0deg,0%,100%,.4) 25%,transparent 0,transparent 50%,hsla(0deg,0%,100%,.4) 0,hsla(0deg,0%,100%,.4) 75%,transparent 0,transparent);
  394. }
  395. ul#player_bar_ul::-webkit-scrollbar-track {
  396. background-color: #f1f1f1;
  397. border-radius: 5px;
  398. }
  399.  
  400. label.player_bar_ul_li_text::-webkit-scrollbar {
  401. width: 5px;
  402. height: 7px;
  403. background-color: #aaa;
  404. }
  405. label.player_bar_ul_li_text::-webkit-scrollbar-thumb {
  406. border: 1px solid rgba(56,56,56,.3411764706);
  407. background-clip: padding-box;
  408. background-color: #a29bb84a;
  409. }
  410. label.player_bar_ul_li_text::-webkit-scrollbar-track {
  411. background-color: #f1f1f1;
  412. }
  413. .player_bar_list_add_div {
  414. display: flex;
  415. height: 40px;
  416. margin: 4px 2px;
  417. }
  418. input#player_bar_list_add_input {
  419. width: 100%;
  420. height: 30px;
  421. background-color: #ffffff;
  422. color: #727378;
  423. font-size: 13px;
  424. border-radius: 0.3rem 0rem 0rem 0.3rem;
  425. padding: 1px 5px;
  426. margin: 5px 0px 5px 0px;
  427. border: 1px solid #00aeeccc;
  428. border-right: none;
  429. box-shadow: 0 0 1px #0000004d;
  430. }
  431. input#player_bar_list_add_input:focus-visible {
  432. border-width: 2px;
  433. border-style: solid;
  434. border-color: #8bb2d9;
  435. outline: -webkit-focus-ring-color auto 0px;
  436. }
  437. button#player_bar_list_add_new_item_btn.added {
  438. background-color: #07e65196;
  439. color: #104f2b;
  440. }
  441. div#player_bar_go.gone {
  442. color: #3f5a14;
  443. font-weight: 600;
  444. background: linear-gradient(-225deg,#9CCC65,#E6EE9C);
  445. box-shadow: inset 0 -2px 0 0 #cde3e6, inset 0 0 1px 1px #c6fd7d, 0 1px 2px 1px rgb(30 90 44 / 40%);
  446. }
  447. /* bar修改菜单 */
  448. div#player_bar_menu {
  449. position: absolute;
  450. border-width: 1px;
  451. border-style: solid;
  452. border-color: #8bb2d9;
  453. box-shadow: 1px 1px 4px 0px #0000004d;
  454. }
  455. div#player_bar_menu_edit {
  456. cursor: pointer;
  457. background-color: #ffffff;
  458. color: black;
  459. box-shadow: inset 0px 0px 0px 0px #8bb2d9;
  460. padding: 2px 6px;
  461. }
  462. div#player_bar_menu_delete {
  463. cursor: pointer;
  464. background-color: #ffff;
  465. box-shadow: inset 0px 1px 0px 0px #8bb2d9;
  466. color: black;
  467. padding: 2px 6px;
  468. }
  469. div#player_bar_menu_edit:hover {
  470. background-color: #00aeec;
  471. color: white;
  472. }
  473. div#player_bar_menu_delete:hover {
  474. background-color: #FF5722;
  475. color: white;
  476. }
  477. /*设置面板*/
  478. div#topNavBar {
  479. width: 80%;
  480. }
  481. nav.navbar.navbar-inverse.navbar-fixed-top.navbar-expand-lg .container {
  482. display: flex;
  483. align-items: center;
  484. justify-content: space-between;
  485. }
  486. button.html2mdButton.ACBetter_setting {
  487. background-color: #56aa56;
  488. color: white;
  489. white-space: nowrap;
  490. float: right;
  491. height: 30px;
  492. margin: 10px;
  493. border: 0px;
  494. }
  495. #ACwingBetter_setting_menu {
  496. z-index: 9999;
  497. border-radius: 0.5rem;
  498. box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  499. display: grid;
  500. position: fixed;
  501. top: 50%;
  502. left: 50%;
  503. width: 270px;
  504. transform: translate(-50%, -50%);
  505. border-radius: 16px;
  506. background-color: #ecf0ff;
  507. border: 6px solid #ffffff;
  508. color: #697e91;
  509. padding: 10px 20px 20px 20px;
  510. }
  511.  
  512. #ACwingBetter_setting_menu .tool-box {
  513. position: absolute;
  514. display: flex;
  515. align-items: center;
  516. justify-content: center;
  517. width: 2.5rem;
  518. height: 2.5rem;
  519. top: 3px;
  520. right: 3px;
  521. }
  522.  
  523. #ACwingBetter_setting_menu .btn-close {
  524. display: flex;
  525. align-items: center;
  526. justify-content: center;
  527. text-align: center;
  528. padding: 10px;
  529. width: 2rem;
  530. height: 2rem;
  531. color: transparent;
  532. font-size: 0;
  533. cursor: pointer;
  534. background-color: #ff000080;
  535. border: none;
  536. border-radius: 10px;
  537. transition: .2s ease all;
  538. }
  539.  
  540. #ACwingBetter_setting_menu .btn-close:hover {
  541. width: 2rem;
  542. height: 2rem;
  543. font-size: 1rem;
  544. color: #ffffff;
  545. background-color: #ff0000cc;
  546. box-shadow: 0 5px 5px 0 #00000026;
  547. }
  548.  
  549. #ACwingBetter_setting_menu .btn-close:active {
  550. width: .9rem;
  551. height: .9rem;
  552. font-size: .9rem;
  553. color: #ffffffde;
  554. --shadow-btn-close: 0 3px 3px 0 #00000026;
  555. box-shadow: var(--shadow-btn-close);
  556. }
  557.  
  558. .checkbox-con {
  559. margin: 10px;
  560. display: flex;
  561. align-items: center;
  562. color: white;
  563. }
  564.  
  565. #ACwingBetter_setting_menu input[type=checkbox]:focus {
  566. outline: 0px;
  567. }
  568.  
  569. .checkbox-con input[type="checkbox"] {
  570. margin: 0px;
  571. appearance: none;
  572. width: 48px;
  573. height: 24px;
  574. border: 2px solid #6b8092;
  575. border-radius: 20px;
  576. background: #f1e1e1;
  577. position: relative;
  578. box-sizing: border-box;
  579. }
  580.  
  581. .checkbox-con input[type="checkbox"]::before {
  582. content: "";
  583. width: 16px;
  584. height: 16px;
  585. background: #6b80927a;
  586. border: 2px solid #6b8092;
  587. border-radius: 50%;
  588. position: absolute;
  589. top: 0;
  590. left: 0;
  591. transform: translate(16%, 12%);
  592. transition: all 0.3s ease-in-out;
  593. }
  594.  
  595. .checkbox-con input[type="checkbox"]::after {
  596. content: url("data:image/svg+xml,%3Csvg xmlns='://www.w3.org/2000/svg' width='23' height='23' viewBox='0 0 23 23' fill='none'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.55021 5.84315L17.1568 16.4498L16.4497 17.1569L5.84311 6.55026L6.55021 5.84315Z' fill='%23EA0707' fill-opacity='0.89'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M17.1567 6.55021L6.55012 17.1568L5.84302 16.4497L16.4496 5.84311L17.1567 6.55021Z' fill='%23EA0707' fill-opacity='0.89'/%3E%3C/svg%3E");
  597. position: absolute;
  598. top: 0;
  599. left: 24px;
  600. }
  601.  
  602. .checkbox-con input[type="checkbox"]:checked {
  603. border: 2px solid #02c202;
  604. background: #e2f1e1;
  605. }
  606.  
  607. .checkbox-con input[type="checkbox"]:checked::before {
  608. background: rgba(2, 194, 2, 0.5);
  609. border: 2px solid #02c202;
  610. transform: translate(160%, 13%);
  611. transition: all 0.3s ease-in-out;
  612. }
  613.  
  614. .checkbox-con input[type="checkbox"]:checked::after {
  615. content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='13' viewBox='0 0 15 13' fill='none'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M14.8185 0.114533C15.0314 0.290403 15.0614 0.605559 14.8855 0.818454L5.00187 12.5L0.113036 6.81663C-0.0618274 6.60291 -0.0303263 6.2879 0.183396 6.11304C0.397119 5.93817 0.71213 5.96967 0.886994 6.18339L5.00187 11L14.1145 0.181573C14.2904 -0.0313222 14.6056 -0.0613371 14.8185 0.114533Z' fill='%2302C202' fill-opacity='0.9'/%3E%3C/svg%3E");
  616. position: absolute;
  617. top: 3px;
  618. left: 4px;
  619. }
  620.  
  621. .checkbox-con label {
  622. margin: 0px 0px 0px 10px;
  623. cursor: pointer;
  624. user-select: none;
  625. }
  626.  
  627. .ACBetter_setting_list {
  628. display: flex;
  629. align-items: center;
  630. margin-top: 18px;
  631. }
  632.  
  633. .checkbox-con button {
  634. cursor: pointer;
  635. display: inline-flex;
  636. padding: 0.5rem 1rem;
  637. background-color: #1aa06d;
  638. color: #ffffff;
  639. font-size: 1rem;
  640. line-height: 1.5rem;
  641. font-weight: 500;
  642. justify-content: center;
  643. width: 100%;
  644. border-radius: 0.375rem;
  645. border: none;
  646. box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  647. }
  648. /*设置面板-tip*/
  649. .help_tip {
  650. margin-right: auto;
  651. }
  652. span.input_label {
  653. font-size: 14px;
  654. }
  655. .help_tip .tip_text {
  656. display: none;
  657. position: absolute;
  658. color: #697e91;
  659. font-weight: 400;
  660. font-size: 14px;
  661. letter-spacing: 0px;
  662. background-color: #ffffff;
  663. padding: 10px;
  664. margin: 5px 0px;
  665. border-radius: 4px;
  666. border: 1px solid #e4e7ed;
  667. box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
  668. z-index: 999;
  669. }
  670. .help_tip .tip_text p {
  671. margin-bottom: 5px;
  672. }
  673. .help_tip .tip_text:before {
  674. content: "";
  675. position: absolute;
  676. top: -20px;
  677. right: -10px;
  678. bottom: -10px;
  679. left: -10px;
  680. z-index: -1;
  681. }
  682. .help-icon {
  683. display: flex;
  684. cursor: help;
  685. width: 15px;
  686. color: #b4b9d4;
  687. margin-left: 5px;
  688. }
  689. .AtBetter_setting_menu .AtBetter_setting_menu_label_text .help_tip .help-icon {
  690. color: #7fbeb2;
  691. }
  692. .help_tip .help-icon:hover + .tip_text, .help_tip .tip_text:hover {
  693. display: block;
  694. cursor: help;
  695. width: 250px;
  696. }
  697. /*更新检查*/
  698. div#update_panel {
  699. z-index: 9999;
  700. position: fixed;
  701. top: 50%;
  702. left: 50%;
  703. width: 240px;
  704. transform: translate(-50%, -50%);
  705. box-shadow: 0px 0px 4px 0px #0000004d;
  706. padding: 10px 20px 20px 20px;
  707. color: #444242;
  708. background-color: #f5f5f5;
  709. border: 1px solid #848484;
  710. border-radius: 8px;
  711. }
  712. div#update_panel #updating {
  713. cursor: pointer;
  714. display: inline-flex;
  715. padding: 0px;
  716. background-color: #1aa06d;
  717. color: #ffffff;
  718. font-size: 1rem;
  719. line-height: 1.5rem;
  720. font-weight: 500;
  721. justify-content: center;
  722. width: 100%;
  723. border-radius: 0.375rem;
  724. border: none;
  725. box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  726. }
  727. div#update_panel #updating a {
  728. text-decoration: none;
  729. color: white;
  730. display: flex;
  731. position: inherit;
  732. top: 0;
  733. left: 0;
  734. width: 100%;
  735. height: 22px;
  736. font-size: 14px;
  737. justify-content: center;
  738. align-items: center;
  739. }
  740. #skip_menu {
  741. display: flex;
  742. margin-top: 10px;
  743. justify-content: flex-end;
  744. align-items: center;
  745. }
  746. #skip_menu .help_tip {
  747. margin-right: 5px;
  748. margin-left: -5px;
  749. }
  750. #skip_menu .help-icon {
  751. color: #f44336;
  752. }
  753. /* Session ID 输入框样式 */
  754. .session-id-input {
  755. width: 100%;
  756. padding: 8px;
  757. margin: 10px 0;
  758. border: 1px solid #ccc;
  759. border-radius: 4px;
  760. box-sizing: border-box;
  761. }
  762. .session-id-label {
  763. display: block;
  764. margin-bottom: 5px;
  765. font-weight: bold;
  766. }
  767. .session-id-container {
  768. margin: 15px 0;
  769. }
  770. `);
  771.  
  772. // 隐藏顶栏
  773. if (hideNavbar & href.includes("/problem/content/")) {
  774. GM_addStyle(`
  775. nav.navbar {
  776. display: none;
  777. }
  778. .base_body {
  779. padding-top: 10px !important;
  780. }
  781. `);
  782. };
  783.  
  784. // 防抖函数
  785. function debounce(callback) {
  786. let timer;
  787. let immediateExecuted = false;
  788. const delay = 500;
  789. return function () {
  790. clearTimeout(timer);
  791. if (!immediateExecuted) { callback.call(this); immediateExecuted = true; }
  792. timer = setTimeout(() => { immediateExecuted = false; }, delay);
  793. };
  794. }
  795.  
  796. // 为元素添加鼠标拖动
  797. function addDraggable(element) {
  798. let isDragging = false;
  799. let initialX, initialY; // 元素的初始位置
  800. let startX, startY, offsetX, offsetY; // 鼠标起始位置,移动偏移量
  801. let isSpecialMouseDown = false; // 选取某些元素时不拖动
  802.  
  803. element.on('mousedown', function (e) {
  804. var elem = $(this);
  805. var elemOffset = elem.offset();
  806. var centerX = elemOffset.left + elem.outerWidth() / 2;
  807. var centerY = elemOffset.top + elem.outerHeight() / 2;
  808. initialX = centerX - window.pageXOffset;
  809. initialY = centerY - window.pageYOffset;
  810.  
  811. isDragging = true;
  812. startX = e.clientX;
  813. startY = e.clientY;
  814.  
  815. isSpecialMouseDown = $(e.target).is('label, p, input, textarea, span');
  816.  
  817. $('body').css('cursor', 'all-scroll');
  818. });
  819.  
  820.  
  821. $(document).on('mousemove', function (e) {
  822. if (!isDragging) return;
  823. // 不执行拖动操作
  824. if ($(e.target).is('label, p, input, textarea, span') || isSpecialMouseDown && !$(e.target).is('input, textarea')) return;
  825. e.preventDefault();
  826. offsetX = e.clientX - startX;
  827. offsetY = e.clientY - startY;
  828. element.css({ top: initialY + offsetY + 'px', left: initialX + offsetX + 'px' });
  829. });
  830.  
  831. $(document).on('mouseup', function () {
  832. isDragging = false;
  833. isSpecialMouseDown = false;
  834. $('body').css('cursor', 'default');
  835. });
  836. }
  837.  
  838. // 随机数生成
  839. function getRandomNumber(numDigits) {
  840. let min = Math.pow(10, numDigits - 1);
  841. let max = Math.pow(10, numDigits) - 1;
  842. return Math.floor(Math.random() * (max - min + 1)) + min;
  843. }
  844.  
  845. // 设置面板
  846. $(document).ready(function () {
  847. $("#topNavBar").after(
  848. "<button class='html2mdButton ACBetter_setting'>AcWingBetter设置</button>"
  849. );
  850. });
  851.  
  852. const ACwingBetterSettingMenuHTML = `
  853. <div class='checkbox-con' id='ACwingBetter_setting_menu'>
  854. <div class="tool-box">
  855. <button class="btn-close">×</button>
  856. </div>
  857. <h3>AcWingBetter设置</h3>
  858. <div class='ACBetter_setting_list'>
  859. <input type="checkbox" id="bottomBar" name="bottomBar" checked>
  860. <label for="bottomBar">美化底栏</label>
  861. </div>
  862. <div class='ACBetter_setting_list'>
  863. <input type="checkbox" id="hideNavbar" name="hideNavbar" checked>
  864. <label for="hideNavbar">题目页隐藏顶栏</label>
  865. </div>
  866. <div class='ACBetter_setting_list'>
  867. <input type="checkbox" id="bingWallpaper" name="bingWallpaper" checked>
  868. <label for="bingWallpaper">Bing每日壁纸</label>
  869. </div>
  870. <div class='ACBetter_setting_list'>
  871. <input type="checkbox" id="widthAdjustment" name="widthAdjustment" checked>
  872. <label for="widthAdjustment">页面宽屏</label>
  873. </div>
  874. <div class='ACBetter_setting_list'>
  875. <input type="checkbox" id="autoPlay" name="autoPlay" checked>
  876. <label for="autoPlay">不自动播放视频</label>
  877. </div>
  878. <div class='ACBetter_setting_list'>
  879. <input type="checkbox" id="acTimer" name="acTimer" checked>
  880. <label for="acTimer">开启AC计时器</label>
  881. </div>
  882. <div class="session-id-container">
  883. <label for="sessionIdInput" class="session-id-label">Session ID</label>
  884. <input type="text" id="sessionIdInput" class="session-id-input" placeholder="输入您的sessionId" value="${getCookie('sessionid') || sessionId}">
  885. <p style="font-size: 12px; color: #666; margin-top: 5px;">用于保持登录(不可用)状态,可在浏览器开发者工具中查看</p>
  886. </div>
  887. <br>
  888. <button id='save'>保存</button>
  889. </div>
  890. `;
  891.  
  892. $(document).ready(function () {
  893. $(".ACBetter_setting").click(function () {
  894. const styleElement = GM_addStyle(darkenPageStyle);
  895.  
  896. $(".ACBetter_setting").attr("disabled", true);
  897. $(".ACBetter_setting").css("background-color", "#e6e6e6");
  898. $(".ACBetter_setting").css("color", "#727378");
  899. $(".ACBetter_setting").css("cursor", "not-allowed");
  900. $("body").append(ACwingBetterSettingMenuHTML);
  901.  
  902. addDraggable($('#ACwingBetter_setting_menu'));
  903. $("#bottomBar").prop("checked", GM_getValue("bottomBar"));
  904. $("#hideNavbar").prop("checked", GM_getValue("hideNavbar"));
  905. $("#bingWallpaper").prop("checked", GM_getValue("bingWallpaper"));
  906. $("#widthAdjustment").prop("checked", GM_getValue("widthAdjustment"));
  907. $("#autoPlay").prop("checked", GM_getValue("autoPlay"));
  908. $("#acTimer").prop("checked", GM_getValue("acTimer"));
  909.  
  910. $("#save").click(function () {
  911. GM_setValue("bottomBar", $("#bottomBar").prop("checked"));
  912. GM_setValue("hideNavbar", $("#hideNavbar").prop("checked"));
  913. GM_setValue("bingWallpaper", $("#bingWallpaper").prop("checked"));
  914. GM_setValue("widthAdjustment", $("#widthAdjustment").prop("checked"));
  915. GM_setValue("autoPlay", $("#autoPlay").prop("checked"));
  916. GM_setValue("acTimer", $("#acTimer").prop("checked"));
  917.  
  918. // 保存sessionId到GM值和cookie
  919. const newSessionId = $("#sessionIdInput").val().trim();
  920. GM_setValue("sessionId", newSessionId);
  921. setCookie('sessionid', newSessionId, 30); // 始终更新cookie
  922.  
  923. $(styleElement).remove();
  924. location.reload();
  925. });
  926.  
  927. // 关闭
  928. $("#ACwingBetter_setting_menu .btn-close").click(function () {
  929. $("#ACwingBetter_setting_menu").remove();
  930. $(".ACBetter_setting").attr("disabled", false);
  931. $(".ACBetter_setting").css("background-color", "#56aa56");
  932. $(".ACBetter_setting").css("color", "white");
  933. $(".ACBetter_setting").css("cursor", "pointer");
  934. $(styleElement).remove();
  935. })
  936. });
  937. });
  938.  
  939. // html2md转换/处理规则
  940. let turndownService = new TurndownService();
  941.  
  942. turndownService.keep(['del']);
  943.  
  944. // 丢弃
  945. turndownService.addRule('remove-by-class', {
  946. filter: function (node) {
  947. return node.classList.contains('html2md-panel') ||
  948. node.classList.contains('html2mdButton');
  949. },
  950. replacement: function (content, node) {
  951. return "";
  952. }
  953. });
  954. turndownService.addRule('remove-script', {
  955. filter: function (node, options) {
  956. return node.tagName.toLowerCase() == "script" && node.type.startsWith("math/tex");
  957. },
  958. replacement: function (content, node) {
  959. return "";
  960. }
  961. });
  962.  
  963. // code block
  964. turndownService.addRule('pre', {
  965. filter: 'pre',
  966. replacement: function (content, node) {
  967. let t = $(node).attr("class").split(/\s+/).slice(-1);
  968. if (t == "hljs") t = "";
  969. return "```" + t + "\n" + content.trim() + "\n```";
  970. }
  971. });
  972.  
  973. // inline math
  974. turndownService.addRule('inline-math', {
  975. filter: function (node, options) {
  976. return node.tagName.toLowerCase() == "span" && node.className == "MathJax";
  977. },
  978. replacement: function (content, node) {
  979. return "$" + $(node).next().text() + "$";
  980. }
  981. });
  982.  
  983. // block math
  984. turndownService.addRule('block-math', {
  985. filter: function (node, options) {
  986. return node.tagName.toLowerCase() == "div" && node.className == "MathJax_Display";
  987. },
  988. replacement: function (content, node) {
  989. return "\n$$\n" + $(node).next().text() + "\n$$\n";
  990. }
  991. });
  992.  
  993. // 按钮面板
  994. function addButtonPanel(parent, suffix, type) {
  995. let htmlString = `<div class='html2md-panel'>
  996. <button class='html2mdButton html2md-view${suffix}'>MarkDown视图</button>
  997. <button class='html2mdButton html2md-cb${suffix}'>Copy</button>
  998. </div>`;
  999. if (type === "this_level") {
  1000. $(parent).before(htmlString);
  1001. } else if (type === "child_level") {
  1002. $(parent).prepend(htmlString);
  1003. }
  1004. }
  1005.  
  1006. function addButtonWithHTML2MD(parent, suffix, type) {
  1007. $(document).on("click", ".html2md-view" + suffix, function () {
  1008. var target, removedChildren = $();
  1009. if (type === "this_level") {
  1010. target = $(".html2md-view" + suffix).parent().next().get(0);
  1011. } else if (type === "child_level") {
  1012. target = $(".html2md-view" + suffix).parent().parent().get(0);
  1013. removedChildren = $(".html2md-view" + suffix).parent().parent().children(':first').detach();
  1014. }
  1015. if (target.viewmd) {
  1016. target.viewmd = false;
  1017. $(this).text("MarkDown视图");
  1018. $(this).removeClass("mdViewed");
  1019. $(target).html(target.original_html);
  1020. } else {
  1021. target.viewmd = true;
  1022. if (!target.original_html) {
  1023. target.original_html = $(target).html();
  1024. }
  1025. if (!target.markdown) {
  1026. target.markdown = turndownService.turndown($(target).html());
  1027. }
  1028. $(this).text("原始内容");
  1029. $(this).addClass("mdViewed");
  1030. $(target).html(`<span class="mdViewContent" oninput="$(this).parent().get(0).markdown=this.value;" style="width:auto; height:auto;">${target.markdown}</span>`);
  1031. }
  1032. // 恢复删除的元素
  1033. if (removedChildren) $(target).prepend(removedChildren);
  1034. });
  1035. }
  1036.  
  1037. function addButtonWithCopy(parent, suffix, type) {
  1038. $(document).on("click", ".html2md-cb" + suffix, function () {
  1039. let target, removedChildren, text;
  1040. if (type === "this_level") {
  1041. target = $(".html2md-cb" + suffix).parent().next().eq(0).clone();
  1042. } else if (type === "child_level") {
  1043. target = $(".html2md-cb" + suffix).parent().parent().eq(0).clone();
  1044. $(target).children(':first').remove();
  1045. }
  1046. if ($(target).find('.mdViewContent').length <= 0) {
  1047. text = turndownService.turndown($(target).html());
  1048. } else {
  1049. text = $(target).find('.mdViewContent').text();
  1050. }
  1051. GM_setClipboard(text);
  1052. $(this).addClass("copied");
  1053. $(this).text("Copied");
  1054. // 更新复制按钮文本
  1055. setTimeout(() => {
  1056. $(this).removeClass("copied");
  1057. $(this).text("Copy");
  1058. }, 2000);
  1059. $(target).remove();
  1060. });
  1061. }
  1062.  
  1063. // 代码块复制按钮
  1064. function codeCopy() {
  1065. $('.hljs code').each(function () {
  1066. let codeBlock = $(this);
  1067. let id = "_" + getRandomNumber(8);
  1068. let beforeButton = $('<button>').text("Copy").addClass(`html2mdButton copy-button${id}`);
  1069. let wrapperDiv = $('<div>').addClass('copy-div');
  1070. $(wrapperDiv).append(beforeButton);
  1071. $(wrapperDiv).css({
  1072. display: "flex",
  1073. justifyContent: "flex-end"
  1074. });
  1075. codeBlock.parent().before(wrapperDiv);
  1076.  
  1077. $(document).on("click", `.copy-button${id}`, debounce(function () {
  1078. GM_setClipboard(codeBlock.text().replace(/\n+$/, ''));
  1079. // 更新复制按钮文本
  1080. var self = this;
  1081. $(self).addClass('copied');
  1082. $(self).text("Copied");
  1083. var self = this;
  1084. setTimeout(function () {
  1085. $(self).removeClass('copied');
  1086. $(self).text("Copy");
  1087. }, 2000);
  1088. }));
  1089. });
  1090. }
  1091.  
  1092. function addConversionButton() {
  1093. // 添加按钮到content部分
  1094. if (!window.location.href.includes("code")) {
  1095. $('div[data-field-name="content"]').each(function () {
  1096. let id = "_question-oi-bd_" + getRandomNumber(8);
  1097. addButtonPanel(this, id, "this_level");
  1098. addButtonWithHTML2MD(this, id, "this_level");
  1099. addButtonWithCopy(this, id, "this_level");
  1100. });
  1101. }
  1102.  
  1103. // 为代码块添加复制按钮
  1104. codeCopy();
  1105. };
  1106.  
  1107. // 播放器添加节点标签功能
  1108. function addPlayerBar(player_bar_video) {
  1109. $('.prism-player').after(`
  1110. <div class='player_bar'>
  1111. <div class='player_bar_list' id='player_bar_list'>
  1112. <ul class='player_bar_ul' id='player_bar_ul'></ul>
  1113. </div>
  1114. <div class='player_bar_go' id='player_bar_go'>Go!</div>
  1115. </div>
  1116. <div class='player_bar_list_add_div'>
  1117. <input class='player_bar_list_add_input' type='text' id='player_bar_list_add_input' placeholder='在这里输入备注内容,点击Add添加一个时间点标记;选中一个标记,点击Go跳转;右键标记,修改或删除'>
  1118. </input>
  1119. <button class='player_bar_list_add_button' id='player_bar_list_add_new_item_btn'>Add</button>
  1120. </div>
  1121. `);
  1122.  
  1123. // 页面路径标识
  1124. const PAGE_IDENTIFIER = window.location.href;
  1125. // 计数器
  1126. let counter = 0;
  1127.  
  1128. // 获取数据
  1129. function getListData() {
  1130. let data = GM_getValue("cookieData");
  1131. if (!data) {
  1132. data = {};
  1133. } else {
  1134. data = JSON.parse(data);
  1135. }
  1136. if (!data[PAGE_IDENTIFIER]) {
  1137. data[PAGE_IDENTIFIER] = [];
  1138. }
  1139. return data[PAGE_IDENTIFIER];
  1140. }
  1141.  
  1142. // 保存数据
  1143. function saveListData(data) {
  1144. let cookieData = GM_getValue("cookieData");
  1145. if (cookieData) {
  1146. cookieData = JSON.parse(cookieData);
  1147. } else {
  1148. cookieData = {};
  1149. }
  1150. cookieData[PAGE_IDENTIFIER] = data;
  1151. GM_setValue("cookieData", JSON.stringify(cookieData));
  1152. }
  1153.  
  1154. // 创建新的li元素
  1155. function createListItemElement(text) {
  1156. const li = $("<li></li>");
  1157. const radio = $("<input type='radio' name='player_bar_ul'></input>").appendTo(li);
  1158. radio.attr("id", counter++);
  1159. const label = $("<label class='player_bar_ul_li_text'></label>").text(text).attr("for", radio.attr("id")).appendTo(li);
  1160.  
  1161. li.on("contextmenu", (event) => {
  1162. event.preventDefault();
  1163. const menu = $("#player_bar_menu");
  1164. menu.css({ display: "block", left: event.pageX, top: event.pageY });
  1165.  
  1166. const deleteItem = $("#player_bar_menu_delete");
  1167. const editItem = $("#player_bar_menu_edit");
  1168.  
  1169. function onDelete() {
  1170. deleteItem.off("click", onDelete);
  1171. const list = $("#player_bar_ul");
  1172. const index = Array.from(list.children()).indexOf(li.get(0));
  1173. const data = getListData();
  1174. data.splice(index, 1);
  1175. saveListData(data);
  1176. li.remove();
  1177. menu.css({ display: "none" });
  1178. }
  1179.  
  1180. function onEdit() {
  1181. editItem.off("click", onEdit);
  1182. const list = $("#player_bar_ul");
  1183. const index = Array.from(list.children()).indexOf(li.get(0));
  1184. const data = getListData();
  1185. label.text(data[index].text);
  1186. const text = prompt("请输入修改后的内容", label.text());
  1187. if (text !== undefined && text !== null) {
  1188. data[index].text = text.trim();
  1189. saveListData(data);
  1190. }
  1191. renderList();
  1192. menu.css({ display: "none" });
  1193. }
  1194.  
  1195. deleteItem.on("click", onDelete);
  1196. editItem.on("click", onEdit);
  1197.  
  1198. $(document).on("click", (event) => {
  1199. if (!menu.get(0).contains(event.target)) {
  1200. menu.css({ display: "none" });
  1201. deleteItem.off("click", onDelete);
  1202. editItem.off("click", onEdit);
  1203. }
  1204. });
  1205. });
  1206.  
  1207. return li;
  1208. }
  1209.  
  1210. // 渲染列表
  1211. function renderList() {
  1212. const listContainer = $("#player_bar_list");
  1213. const list = $("#player_bar_ul");
  1214. list.empty();
  1215. const data = getListData();
  1216. data.forEach((item) => {
  1217. list.append(createListItemElement(item.text));
  1218. });
  1219. }
  1220.  
  1221. // 新增列表项
  1222. function addNewItem() {
  1223. const input = $("#player_bar_list_add_input");
  1224. const text = input.val().trim();
  1225. if (text === "") {
  1226. alert("请输入内容");
  1227. return;
  1228. }
  1229. const data = getListData();
  1230. data.push({ text: text, time: player_bar_video.currentTime });
  1231. saveListData(data);
  1232. const list = $("#player_bar_ul");
  1233. list.append(createListItemElement(text));
  1234. input.val("");
  1235. }
  1236.  
  1237. // 为添加按钮添加事件处理程序
  1238. const player_bar_add_button = $("#player_bar_list_add_new_item_btn");
  1239. player_bar_add_button.on("click", () => {
  1240. addNewItem();
  1241. player_bar_add_button.addClass('added');
  1242. player_bar_add_button.text("Added");
  1243. setTimeout(() => {
  1244. player_bar_add_button.removeClass('added');
  1245. player_bar_add_button.text("Add");
  1246. }, 2000);
  1247. });
  1248.  
  1249. // 渲染列表
  1250. renderList();
  1251.  
  1252. // 跳转按钮
  1253. const click_player_bar_go = $("#player_bar_go");
  1254. click_player_bar_go.on("click", () => {
  1255. const selected = $('input[name="player_bar_ul"]:checked');
  1256. if (selected.length) {
  1257. const data = getListData();
  1258. const index = selected.parent().index();
  1259. player_bar_video.currentTime = data[index].time;
  1260. click_player_bar_go.addClass('gone');
  1261. click_player_bar_go.text("Gone");
  1262. setTimeout(() => {
  1263. click_player_bar_go.removeClass('gone');
  1264. click_player_bar_go.text("Go!");
  1265. }, 2000);
  1266. } else {
  1267. alert("请选择一项");
  1268. }
  1269. });
  1270.  
  1271. // 创建自定义菜单
  1272. const menu = $("<div id='player_bar_menu' style='display: none;'></div>");
  1273. menu.html(`
  1274. <div id='player_bar_menu_edit'>修改</div>
  1275. <div id='player_bar_menu_delete'>删除</div>
  1276. `);
  1277. $("body").append(menu);
  1278. }
  1279.  
  1280. function formatTime(time) {
  1281. var seconds = Math.floor((time / 1000) % 60);
  1282. var minutes = Math.floor((time / (1000 * 60)) % 60);
  1283. var hours = Math.floor((time / (1000 * 60 * 60)) % 24);
  1284. var days = Math.floor(time / (1000 * 60 * 60 * 24));
  1285.  
  1286. var timeString = '';
  1287.  
  1288. if (days > 0) {
  1289. timeString += days + '天';
  1290. }
  1291.  
  1292. if (hours > 0) {
  1293. timeString += hours + '小时';
  1294. }
  1295.  
  1296. if (minutes > 0) {
  1297. timeString += minutes + '分钟';
  1298. }
  1299.  
  1300. if (seconds > 0) {
  1301. timeString += seconds + '秒';
  1302. }
  1303.  
  1304. return timeString;
  1305. }
  1306.  
  1307. // AC计时器
  1308. function acTiming() {
  1309. var startTime = new Date();
  1310. var timer = setInterval(function () {
  1311. var status = $('#submit-code-status-value-id').text().trim();
  1312.  
  1313. if (status === 'Accepted') {
  1314. clearInterval(timer);
  1315.  
  1316. var endTime = new Date();
  1317. var totalTime = endTime - startTime;
  1318.  
  1319. var timeString = formatTime(totalTime);
  1320. $('#submit-code-status-value-id').after('<div class="time-info">耗时:' + timeString + ' 要重新开始计时请刷新页面</div>');
  1321. }
  1322. }, 500);
  1323. }
  1324.  
  1325. $(document).ready(function () {
  1326. // 检查sessionId和登录(不可用)状态
  1327. checkSessionAndLogin();
  1328.  
  1329. if (acTimer && window.location.href.includes("/problem/content/")) acTiming();
  1330.  
  1331. // 让某些链接在新窗口打开
  1332. var regExps = [
  1333. /常用代码模板/,
  1334. /example/,
  1335. /test/
  1336. ];
  1337. var aTags = document.getElementsByTagName('a');
  1338. for (var i = 0; i < aTags.length; i++) {
  1339. for (var j = 0; j < regExps.length; j++) {
  1340. if (regExps[j].test(aTags[i].textContent)) {
  1341. aTags[i].setAttribute('target', '_blank');
  1342. break;
  1343. }
  1344. }
  1345. }
  1346. // 自动恢复进度条
  1347. (function checkAndPlay() {
  1348. if ($('.play-jump').length > 0) {
  1349. $('.play-jump').click();
  1350. if (GM_getValue("autoPlay") === true) {
  1351. let player_bar_video = document.querySelector('video');
  1352. if (!player_bar_video.paused) player_bar_video.pause();
  1353. }
  1354. } else {
  1355. setTimeout(checkAndPlay, 500);
  1356. }
  1357. })();
  1358. // 调整视频高度
  1359. $('.prism-player').height($('.prism-player').width() / 1.7);
  1360.  
  1361. // 添加按钮
  1362. addConversionButton();
  1363. // 移除广告元素
  1364. let ADidADList = ["1024-activity", "test"];
  1365. ADtraverseDom(document.body);
  1366. function ADtraverseDom(node) {
  1367. if (node.nodeType === Node.ELEMENT_NODE && ADidADList.includes(node.id)) {
  1368. node.parentNode.removeChild(node);
  1369. } else {
  1370. for (let i = 0; i < node.childNodes.length; i++) {
  1371. ADtraverseDom(node.childNodes[i]);
  1372. }
  1373. }
  1374. }
  1375. // 修改打卡页代码框默认高度
  1376. var element = document.getElementById("martor-content");
  1377. if (element) {
  1378. var style = window.getComputedStyle(element);
  1379. element.style.height = "55vh";
  1380. }
  1381.  
  1382. var player_bar_video = document.querySelector('video');
  1383. if (player_bar_video != null) addPlayerBar(player_bar_video);
  1384. });

QingJ © 2025

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