AcWing Better!

AcWing界面美化,功能增强,视频时间点标记跳转,代码markdown一键复制

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