MCBBS Extender

MCBBS行为拓展/样式修复

  1. // ==UserScript==
  2. // @name MCBBS Extender
  3. // @namespace https://i.zapic.cc
  4. // @version release-2.1.0
  5. // @description MCBBS行为拓展/样式修复
  6. // @author Zapic
  7. // @match https://*.mcbbs.net/*
  8. // @run-at document-body
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. // Core
  13. (() => {
  14. let ShouldRun = true;
  15. // jQuery检查
  16. if (typeof jQuery == "undefined") {
  17. console.error("This page does NOT contain JQuery,MCBBS Extender will not work.");
  18. ShouldRun = false;
  19. }
  20. //在手机页面主动禁用
  21. if (document.getElementsByTagName('meta').viewport) {
  22. console.log("MCBBS Extender not fully compatible with Moblie page,exit manually");
  23. ShouldRun = false;
  24. }
  25. //夹带私货
  26. console.log(" %c Zapic's Homepage %c https://i.zapic.moe ", "color: #ffffff; background: #E91E63; padding:5px;", "background: #000; padding:5px; color:#ffffff");
  27. // Gear浏览器上的Polyfill
  28. if(typeof console.debug == "undefined") {
  29. console.debug = function() {};
  30. }
  31. // 基本信息初始化
  32. let version = "v2.1.0";
  33. let vercode = 121140;
  34. let valueList = {};
  35. let configList = [];
  36. // 加载ValueStorage
  37. try {
  38. valueList = JSON.parse(localStorage.getItem("MExt_config"));
  39. if (typeof valueList != "object" || valueList == null) {
  40. valueList = {};
  41. localStorage.setItem("MExt_config", "{}")
  42. }
  43. } catch (ignore) {
  44. valueList = {};
  45. localStorage.setItem("MExt_config", "{}")
  46. }
  47. // 导出模块
  48. let exportModule = (...modules) => {
  49. if (!ShouldRun) { return; }
  50. for (let m of modules) {
  51. try {
  52. moduleLoader(m);
  53. } catch (e) {
  54. console.error("Error occurred while try to load a module:\n" + e);
  55. }
  56. }
  57. }
  58. let $ = unsafeWindow.jQuery;
  59. let dlg = (m) => {
  60. console.debug("[MCBBS Extender]" + m);
  61. };
  62. let setValue = (name, val) => {
  63. valueList[name] = val;
  64. localStorage.setItem("MExt_config", JSON.stringify(valueList));
  65. }
  66. let getValue = (name) => {
  67. return valueList[name];
  68. }
  69. let deleteValue = (name) => {
  70. delete valueList[name];
  71. localStorage.setItem("MExt_config", JSON.stringify(valueList));
  72. }
  73. $('head').append('<style id="MExt_CoreStyle"></style>');
  74. let appendStyle = (style) => {
  75. document.getElementById('MExt_CoreStyle').innerHTML += "\n" + style;
  76. };
  77. let getRequest = (variable, url = "") => {
  78. let query = url ? /\?(.*)/.exec(url)[1] : window.location.search.substring(1);
  79. let vars = query.split("&");
  80. for (let i = 0; i < vars.length; i++) {
  81. let pair = vars[i].split("=");
  82. if (pair[0] == variable) {
  83. return pair[1];
  84. }
  85. }
  86. return (false);
  87. }
  88. // 模块加载器
  89. let moduleLoader = (module) => {
  90. // 载入配置项
  91. if (typeof module.config !== "undefined") {
  92. module.config.forEach((v) => {
  93. if (typeof getValue(v.id) == "undefined") {
  94. setValue(v.id, v.default);
  95. }
  96. let config = v;
  97. v.value = getValue(v.id);
  98. configList.push(config);
  99. });
  100. }
  101. // 判断是否应该运行
  102. if (typeof module.runcase == "function") {
  103. if (!module.runcase()) {
  104. return;
  105. }
  106. }
  107. // 加载模块CSS
  108. if (typeof module.style == 'string') {
  109. appendStyle(module.style);
  110. }
  111. // 运行模块Core
  112. if (typeof module.core == "function") {
  113. module.core();
  114. }
  115. }
  116.  
  117. // 钩住DiscuzAjax函数,使其触发全局事件
  118. let __ajaxpost = ajaxpost;
  119. ajaxpost = (formid, showid, waitid, showidclass, submitbtn, recall) => {
  120. let relfunc = () => {
  121. if (typeof recall == 'function') {
  122. recall();
  123. } else {
  124. eval(recall);
  125. }
  126. $(this).trigger('DiscuzAjaxPostFinished');
  127. }
  128. __ajaxpost(formid, showid, waitid, showidclass, submitbtn, relfunc);
  129. }
  130. let __ajaxget = ajaxget;
  131. ajaxget = (url, showid, waitid, loading, display, recall) => {
  132. let relfunc = () => {
  133. if (typeof recall == 'function') {
  134. recall();
  135. } else {
  136. eval(recall);
  137. }
  138. $(this).trigger('DiscuzAjaxGetFinished');
  139. }
  140. __ajaxget(url, showid, waitid, loading, display, relfunc);
  141. }
  142. dlg("Hooked into Discuz Ajax");
  143.  
  144. // 对外暴露API
  145. let MExt = {
  146. "ValueStorage": {
  147. "get": getValue,
  148. "set": setValue,
  149. "delete": deleteValue
  150. },
  151. "exportModule": exportModule,
  152. "debugLog": dlg,
  153. "versionName": version,
  154. "versionCode": vercode,
  155. "jQuery": $,
  156. "configList": configList,
  157. "Units": {
  158. "appendStyle": appendStyle,
  159. "getRequest": getRequest
  160. }
  161. };
  162. unsafeWindow.MExt = MExt;
  163. dlg("Core loaded.");
  164. })();
  165.  
  166. // Settings
  167. (() => {
  168. let MExt = unsafeWindow.MExt;
  169. let $ = MExt.jQuery;
  170. let Md = {
  171. "style": `.conf_contain {
  172. max-height: 45vh;
  173. overflow-y: auto;
  174. padding-right: 5px;
  175. overflow-x: hidden;
  176. scrollbar-color: rgba(0, 0, 0, 0.17) #f7f7f7;
  177. scrollbar-width: thin;
  178. }
  179.  
  180. .alert_info ::-webkit-scrollbar {
  181. background: #f7f7f7;
  182. height: 7px;
  183. width: 7px
  184. }
  185.  
  186. .alert_info ::-webkit-scrollbar-thumb:hover {
  187. background: rgba(0, 0, 0, 0.35);
  188. }
  189.  
  190. .alert_info ::-webkit-scrollbar-thumb {
  191. background: rgba(0, 0, 0, 0.17);
  192. }
  193.  
  194. .conf_item {
  195. line-height: 1.2;
  196. margin-bottom: 5px;
  197. }
  198.  
  199. .conf_title {
  200. font-weight: 1000;
  201. }
  202.  
  203. .conf_subtitle {
  204. font-size: 10px;
  205. color: rgba(0, 0, 0, 0.5);
  206. padding-right: 40px;
  207. display: block;
  208. }
  209.  
  210. .conf_check {
  211. float: right;
  212. margin-top: -25px;
  213. }
  214.  
  215. .conf_input {
  216. float: right;
  217. width: 30px;
  218. margin-top: -27px;
  219. }
  220.  
  221. .conf_longinput {
  222. width: 100%;
  223. margin-top: 5px;
  224. }
  225.  
  226. .conf_textarea {
  227. width: calc(100% - 4px);
  228. margin-top: 5px;
  229. resize: vertical;
  230. min-height: 50px;
  231. }`,
  232. "core": () => {
  233. let getRequest = MExt.Units.getRequest;
  234. $(() => {
  235. // 发送警告
  236. if (location.pathname == "/forum.php" && getRequest('mod') == "post" && getRequest('action') == "newthread" && getRequest('fid') == "246") {
  237. $("body").append($(`<div id="close_script_alert" style="max-width:430px;position: fixed; left: 20px; top: 80px; z-index: 9999; transform: matrix3d(1, 0, 0, 0.0001, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.025) translateX(-120%); background: rgba(228, 0, 0, 0.81); color: white; padding: 15px; transition-duration: 0.3s; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.66) 2px 2px 5px 0px;"><h1 style="font-size: 3em;float: left;margin-right: 12px;font-weight: 500;margin-top: 6px;">警告</h1><span style="font-size: 1.7em;">您正在向反馈与投诉版发表新的帖子</span><br>如果您正在向论坛报告论坛内的Bug,请先关闭此脚本再进行一次复现,以确保Bug不是由MCBBS Extender造成的.</div>`));
  238. setTimeout(() => { $("#close_script_alert")[0].style.transform = "matrix3d(1, 0, 0, 0.0001, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.025)"; }, 10);
  239. setTimeout(() => { $("#close_script_alert")[0].style.transform = "none"; }, 300);
  240. setTimeout(() => { $("#close_script_alert")[0].style.transform = "translateX(-120%)"; }, 10000);
  241. MExt.debugLog("Warning send");
  242. }
  243. // 设置界面初始化
  244. $("#user_info_menu .user_info_menu_btn").append("<li><a href='javascript: void(0);' id=\"MExt_config\">MCBBS Extender 设置</a></li>");
  245. let confwinContent = '<style>body{overflow:hidden}.altw{width:700px;max-width:95vw;}.alert_info {background-image: unset;padding-left: 20px;padding-right: 17px;}</style><div class="conf_contain">';
  246. let inputType = {
  247. "check": '',
  248. "num": '',
  249. "text": '',
  250. "textarea": ''
  251. };
  252. MExt.configList.forEach((v) => {
  253. switch (v.type) {
  254. case "check":
  255. inputType.check += '<p class="conf_item"><span class="conf_title">' + v.name + '</span><br><span class="conf_subtitle">' + v.desc + '</span><input class="conf_check" type="checkbox" id="in_' + v.id + '"></input></p>';
  256. break;
  257. case "num":
  258. inputType.num += '<p class="conf_item"><span class="conf_title">' + v.name + '</span><br><span class="conf_subtitle">' + v.desc + '</span><input type="number" class="conf_input" id="in_' + v.id + '"></input></p>';
  259. break;
  260. case "text":
  261. inputType.text += '<p class="conf_item"><span class="conf_title">' + v.name + '</span><br><span class="conf_subtitle">' + v.desc + '</span><input type="text" class="conf_longinput" id="in_' + v.id + '"></input></p>';
  262. break;
  263. case "textarea":
  264. inputType.textarea += '<p class="conf_item"><span class="conf_title">' + v.name + '</span><br><span class="conf_subtitle">' + v.desc + '</span><textarea class="conf_textarea" id="in_' + v.id + '"></textarea></p>';
  265. break;
  266. default:
  267. inputType.check += '<p class="conf_item"><span class="conf_title">' + v.name + '</span><br><span class="conf_subtitle">' + v.desc + '</span><input class="conf_check" type="checkbox" id="in_' + v.id + '"></input></p>';
  268. break;
  269. }
  270. });
  271. confwinContent += inputType.check + inputType.num + inputType.text + inputType.textarea + '</div>';
  272. MExt.debugLog('Setting window content loaded.');
  273. $("#MExt_config").on("click", () => {
  274. unsafeWindow.showDialog(
  275. confwinContent,
  276. "confirm",
  277. "MCBBS Extender 设置<a href=\"https://afdian.net/@Zapic\" target=\"_blank\" style=\"margin-left: 385px;color: #369;text-decoration: underline;\">爱发电赞助</a><a href=\"https://github.com/Proj-MExt/Modules-Repo/\" target=\"_blank\" style=\"margin-left: 15px;color: #369;text-decoration: underline;\">插件市场</a>",
  278. () => {
  279. MExt.configList.forEach((v) => {
  280. let val = '';
  281. if (v.type == "num" || v.type == "text" || v.type == "textarea") {
  282. val = $("#in_" + v.id).val();
  283. } else {
  284. val = $("#in_" + v.id).prop("checked");
  285. }
  286. MExt.ValueStorage.set(v.id, val);
  287. });
  288. setTimeout(() => {
  289. unsafeWindow.showDialog("设置已保存,刷新生效<style>.alert_info{background:url(https://www.mcbbs.net/template/mcbbs/image/right.gif) no-repeat 8px 8px}</style>", "confirm", "", () => { location.reload() }, true, () => {}, "", "刷新", "确定");
  290. });
  291. },
  292. true,
  293. () => {},
  294. "MCBBS Extender " + MExt.versionName + " - 世予可爱捏"
  295. );
  296. MExt.configList.forEach((v) => {
  297. if (v.type == "num" || v.type == "text" || v.type == "textarea") {
  298. $("#in_" + v.id).val(MExt.ValueStorage.get(v.id));
  299. } else {
  300. $("#in_" + v.id).prop("checked", MExt.ValueStorage.get(v.id));
  301. }
  302. });
  303. });
  304. });
  305. }
  306. };
  307. MExt.exportModule(Md);
  308. })();
  309.  
  310. // Update Manager
  311. (() => {
  312. let updatelist = [
  313. "1. 修复 帖子高亮 部分用户高亮出现异常的情况",
  314. "2. 孩子没有钱了, 赏口饭吃吧! -> <a href=\"https://afdian.net/@Zapic\" target=\"_blank\" style=\"color: #369;text-decoration: underline;\">爱发电赞助</a>"
  315. ];
  316. unsafeWindow.MExt.exportModule({
  317. "core": () => {
  318. if (typeof unsafeWindow.MExt.ValueStorage.get("LastVersion") == "undefined") {
  319. unsafeWindow.MExt.ValueStorage.set("LastVersion", unsafeWindow.MExt.versionCode);
  320. showDialog("<b>欢迎使用MCBBS Extender</b>.<br>本脚本的设置按钮已经放进入了您的个人信息菜单里,如需调整设置请在个人信息菜单里查看.<br><a href=\"https://afdian.net/@Zapic\" target=\"_blank\" style=\"color: #E91E63;text-decoration: underline;\">在爱发电赞助我!</a>", "right", "欢迎", () => {
  321. showMenu('user_info');
  322. unsafeWindow.MExt.jQuery("#MExt_config").css("background-color", "#E91E63").css("color", "#fff");
  323. setTimeout(() => {
  324. hideMenu('user_info_menu');
  325. unsafeWindow.MExt.jQuery("#MExt_config").css("background-color", "").css("color", "");
  326. }, 3000);
  327. });
  328. return;
  329. }
  330. if (unsafeWindow.MExt.ValueStorage.get("LastVersion") == unsafeWindow.MExt.versionCode) { return; }
  331. let updateContent = '';
  332. updatelist.forEach((v) => {
  333. updateContent += "<br>" + v;
  334. });
  335. showDialog("<b>MCBBS Extender 已经更新至 " + unsafeWindow.MExt.versionName + "</b>" + updateContent, "right");
  336. unsafeWindow.MExt.ValueStorage.set("LastVersion", unsafeWindow.MExt.versionCode);
  337. }
  338. });
  339. })();
  340.  
  341. //Modules
  342. (() => {
  343. let staticRes = {
  344. "atBtnImage": "data:image/png;base64,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",
  345. "medalReflectImage": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAA3CAYAAACGnvPUAAAAAXNSR0IArs4c6QAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA1UlEQVRYw+3Qy6rBARRGcQcjl1zCG5AkkY48gUiEMHU/7/8GS/vUHoqif1/ZgzX/tVLAn0qpwAQmMIH5NsxECWM1gYMKxsoBUxWM1wKOKhgrD8xUMF47yUvPMFYBmKtgvA5wUsFYRWChgrF+gC5wVsB4JWCpgvFLvU9dehfjlYGVCsYv9YGLAsarAGsVjJUGBsBVAeNVgY0Kxi8NX7mUBMarAVsVjF/6fXQpaYxXB3YqGCsDjICbAsZrAHsVjJUFxiqY/wITmMAEJjCBCUxgAhOYb8PcAbo5rkGPsZmjAAAAAElFTkSuQmCC",
  346. "rainbowBtnImage": "data:image/png;base64,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"
  347. };
  348. let MExt = unsafeWindow.MExt;
  349. let $ = MExt.jQuery;
  350. let dlg = MExt.debugLog;
  351. let Stg = MExt.ValueStorage;
  352. let fixCodeBlock = {
  353. "style": `pre:not([id]) code {
  354. background: #f7f7f7;
  355. display: block;
  356. font-family: Monaco, Consolas, 'Lucida Console', 'Courier New', serif;
  357. font-size: 12px;
  358. line-height: 1.8em;
  359. padding: 10px;
  360. border: #ccc solid 1px;
  361. position: relative;
  362. }
  363.  
  364. .pl .blockcode ol li:hover {
  365. background: none;
  366. color: #666
  367. }
  368.  
  369. .pl .blockcode ol li {
  370. white-space: nowrap;
  371. list-style: none;
  372. padding-left:0;
  373. margin-left:0;
  374. }
  375.  
  376. .pl pre em, .pl .blockcode em {
  377. font-size: 0;
  378. }
  379.  
  380. .pl pre em::after, .pl .blockcode em::after {
  381. content: 'Copy';
  382. position: absolute;
  383. top: 3px;
  384. right: 7px;
  385. display: block;
  386. font-size: 14px;
  387. border: #369 dashed 1px;
  388. padding: 0 7px;
  389. border-radius: 3px;
  390. transition-duration: .1s;
  391. opacity: 0.3;
  392. color: #369;
  393. cursor: pointer;
  394. font-family: Monaco, Consolas, 'Lucida Console', 'Courier New', serif;
  395. }
  396.  
  397. .pl .blockcode,.pl pre:not([id]) {
  398. position: relative;
  399. padding: 0;
  400. }
  401.  
  402. .pl pre em:active::after, .pl .blockcode em:active::after {
  403. background: #369;
  404. border: #369 solid 2px;
  405. color: white;
  406. }
  407.  
  408. .pl .blockcode em:hover::after, .pl pre em:hover::after {
  409. opacity: 1;
  410. }
  411.  
  412. .pl .blockcode div[id], pre:not([id]) code {
  413. max-height: 500px;
  414. overflow: auto;
  415. padding: 10px 30px 5px 50px;
  416. background: #F7F7F7 url(https://www.mcbbs.net/template/mcbbs/image/codebg.gif) repeat-y 0 0;
  417. scrollbar-width: thin;
  418. }
  419.  
  420. .pl .blockcode div[id]::-webkit-scrollbar, pre:not([id]) code::-webkit-scrollbar {
  421. width: 7px;
  422. height: 7px;
  423. }
  424.  
  425. .pl .blockcode div[id]::-webkit-scrollbar-thumb, pre:not([id]) code::-webkit-scrollbar-thumb {
  426. background: #00000040
  427. }
  428.  
  429. .line-counter {
  430. position: sticky;
  431. float: left;
  432. left: -50px;
  433. line-height: 1.8em;
  434. padding-top: 3px;
  435. user-select: none;
  436. margin: -4px 0px -50px -50px;
  437. border-right: #d6d6d6 solid 1px;
  438. width: 38px;
  439. background: #ededed;
  440. font-size: 12px;
  441. font-family: Monaco, Consolas, 'Lucida Console', 'Courier New', serif;
  442. padding-right: 4px;
  443. text-align: right;
  444. }
  445.  
  446. .pl .blockcode ol {
  447. margin: 0!important;
  448. }
  449.  
  450. .pl .t_table .blockcode ol li {
  451. width:0;
  452. }
  453. pre:not([id]) code br{
  454. display: none;
  455. }
  456. `,
  457. "core": () => {
  458. // 构建代码行计数器
  459. let LnBuilder = (ln) => {
  460. let str = "";
  461. for (let i = 1; i <= ln; i++) {
  462. str += (i < 10 ? "0" + i.toString() : i.toString()) + ".\n";
  463. }
  464. return str;
  465. };
  466. // 为代码块添加行数显示与复制按钮
  467. let fixCode = () => {
  468. $(".pl pre:not([id]) code:not([code-fixed])").attr("code-fixed",'').each((i, v) => {
  469. // 构建计数器
  470. let ln = v.innerHTML.split("\n").length;
  471. let lnC = LnBuilder(ln);
  472. let counter = document.createElement("div");
  473. counter.className = "line-counter";
  474. counter.innerText = lnC;
  475. // 构建按钮
  476. let copy = document.createElement("em");
  477. copy.className = "code-copy";
  478. copy.addEventListener("click", (e) => {
  479. let n = e.currentTarget.previousSibling;
  480. copycode(n);
  481. });
  482. v.prepend(counter);
  483. v.parentElement.append(copy);
  484. });
  485. $(".pl div.blockcode:not([code-fixed])").attr("code-fixed",'').each((i, v) => {
  486. // 构建计数器
  487. let ln = v.firstElementChild.firstElementChild.childElementCount;
  488. let lnC = LnBuilder(ln);
  489. let counter = document.createElement("div");
  490. counter.className = "line-counter";
  491. counter.innerText = lnC;
  492. v.firstElementChild.prepend(counter);
  493. });
  494. dlg('Line counter appended.');
  495. }
  496. copycode = (t) => {
  497. console.log(t.firstElementChild);
  498. setCopy(t.innerText.replace(/\n\n/g, "\n").replace(t.firstElementChild.innerText,''), "代码已复制到剪贴板");
  499. dlg("Code copied.");
  500. };
  501. $(fixCode);
  502. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", fixCode);
  503. },
  504. "config": [{
  505. "id": "fixCodeBlock",
  506. "default": true,
  507. "type": "check",
  508. "name": "美化代码块样式",
  509. "desc": "修正代码块的一些样式,如滚动条."
  510. }],
  511. "runcase": () => { return MExt.ValueStorage.get("fixCodeBlock"); }
  512. };
  513. let queryMessage = {
  514. "runcase": () => { return MExt.ValueStorage.get("queryMessage") },
  515. "config": [{
  516. "id": "queryMessage",
  517. "default": true,
  518. "type": "check",
  519. "name": "后台轮询消息",
  520. "desc": "在后台自动查询是否有新的消息并推送,需保证至少打开一个页面."
  521. }, {
  522. "id": "queryMessageInterval",
  523. "default": 60,
  524. "type": "num",
  525. "name": "后台轮询消息间隔",
  526. "desc": "两次轮询消息之间的间隔,单位秒.注意,过低的值可能会导致你被论坛屏蔽,超过200的值可能会导致消息反复推送."
  527. }],
  528. "core": () => {
  529. let checkNotifica = (noNotifica = false) => {
  530. if (localStorage.getItem("MExt_ActiveQueryId") != queryId) {
  531. return false;
  532. }
  533. dlg("Checking message...");
  534. $.get("/forum.php?mod=misc", (d) => {
  535. // 设置最后通知时间为当前时间,以防止反复推送
  536. localStorage.setItem('notifica-time', new Date().getTime());
  537. let dom = $(d);
  538. // 获得顶栏图标类
  539. let noticlass = dom.find("#myprompt").attr("class");
  540. // 获得通知菜单元素
  541. let notimenu = dom.filter("#myprompt_menu");
  542. // 将顶栏图标类写入当前页
  543. $("#myprompt").attr("class", noticlass);
  544. // 将通知菜单写入当前页
  545. $("#myprompt_menu").html(notimenu.html());
  546. // 获得消息内容,用作缓存
  547. let noticontent = notimenu.html();
  548. // 判断是否应该发送消息
  549. if (!noNotifica && localStorage.getItem("MExt_LastNoticeContent") != noticontent) {
  550. // 获得通知脚本(暴力)
  551. let scp = dom.filter("script[src*=html5notification]").nextUntil("div").last().text();
  552. // 将最后通知时间设置为1,强行启用通知
  553. localStorage.setItem('notifica-time', 1);
  554. // 执行通知脚本
  555. eval(scp);
  556. dlg("Notifica sent.");
  557. // 写入消息缓存
  558. localStorage.setItem("MExt_LastNoticeContent", noticontent);
  559. localStorage.setItem("MExt_LastNoticeCount", noticlass);
  560. }
  561. });
  562. }
  563. // 刷新消息缓存
  564. let flushContent = () => {
  565. $.get("/forum.php?mod=misc", (d) => {
  566. let dom = $(d);
  567. let noticontent = dom.filter("#myprompt_menu").html();
  568. let noticlass = dom.find("#myprompt").attr("class");
  569. // 写入消息缓存
  570. localStorage.setItem("MExt_LastNoticeContent", noticontent);
  571. localStorage.setItem("MExt_LastNoticeCount", noticlass);
  572. });
  573. }
  574. // 生成queryID,用于页面间的互斥
  575. let queryId = hash(new Date().getTime().toLocaleString(), 16);
  576. // 判断是否在消息页面||最后通知时间是否超过200秒
  577. if ((location.pathname == "/home.php" && (getRequest('do') == "pm" || getRequest('do') == "notice")) || new Date().getTime() - localStorage.getItem("notifica-time") > 200000) {
  578. flushContent();
  579. } else {
  580. checkNotifica();
  581. }
  582. dlg("Query id is " + queryId + ".");
  583. // 运行定时器,用于检查其他页面是否在运行
  584. setInterval(() => {
  585. if (localStorage.getItem("MExt_LastQuery") == "") {
  586. localStorage.setItem("MExt_LastQuery", 0);
  587. }
  588. let nowtime = Math.floor(new Date().getTime() / 1000);
  589. if ((localStorage.getItem("MExt_ActiveQueryId") == "" || nowtime - localStorage.getItem("MExt_LastQuery") > 5) && localStorage.getItem("MExt_ActiveQueryId") != queryId) {
  590. localStorage.setItem("MExt_ActiveQueryId", queryId);
  591. checkNotifica();
  592. dlg("Kick off inactive querier,start query.");
  593. }
  594. if (localStorage.getItem("MExt_ActiveQueryId") == queryId) {
  595. localStorage.setItem("MExt_LastQuery", nowtime);
  596. }
  597. }, 1000);
  598. dlg("Running checker actived.");
  599. // 判断是否有HTML5Notification
  600. if (!unsafeWindow.Html5notification) {
  601. $.getScript("data/cache/html5notification.js?xm6");
  602. dlg("Html5notification added.");
  603. }
  604. //
  605. $(window).on("focus", () => {
  606. dlg("Get content from cache");
  607. $("#myprompt_menu").html(localStorage.getItem("MExt_LastNoticeContent"));
  608. $("#myprompt").attr("class", localStorage.getItem("MExt_LastNoticeCount"));
  609. });
  610. // 定时运行检查函数
  611. setInterval(checkNotifica, MExt.ValueStorage.get('queryMessageInterval') * 1000);
  612. dlg("Message query actived.");
  613. }
  614. };
  615. let rememberPage = {
  616. "runcase": () => { return MExt.ValueStorage.get("rememberPage") },
  617. "config": [{
  618. "id": "rememberPage",
  619. "default": true,
  620. "type": "check",
  621. "name": "板块内翻页记忆",
  622. "desc": "点击板块内下一页按钮时记忆当前页."
  623. }],
  624. "core": () => {
  625. $(() => {
  626. let npbtn = $("#autopbn");
  627. if (npbtn.length) {
  628. // 绑定事件
  629. let orgfunc = npbtn[0].onclick;
  630. npbtn[0].onclick = null;
  631. npbtn.on("click", () => {
  632. if (npbtn.html() == "正在加载, 请稍后...") { return false; }
  633. let nextpageurl = npbtn.attr('rel');
  634. let curpage = parseInt(npbtn.attr('curpage'));
  635. npbtn.attr('curpage', curpage + 1);
  636. nextpageurl = nextpageurl.replace(/&page=\d+/, '&page=' + (curpage + 1));
  637. $("#threadlisttableid").append("<a class=\"mext_rempage\" rel=\"" + nextpageurl + "\"></a>")
  638. history.replaceState(null, null, nextpageurl);
  639. orgfunc();
  640. });
  641. $("#separatorline").after("<a class=\"mext_rempage\" rel=\"" + window.location + "\"></a>");
  642. let timer = -1;
  643. // 事件防抖
  644. $(window).on("scroll", () => {
  645. clearTimeout(timer);
  646. timer = setTimeout(() => {
  647. let scroll = document.scrollingElement.scrollTop - window.innerHeight / 2;
  648. let url = null;
  649. document.querySelectorAll(".mext_rempage").forEach((v, i) => {
  650. let vtop = v.offsetTop;
  651. if (vtop < scroll || i == 0) {
  652. url = v.rel;
  653. }
  654. });
  655. if (url) {
  656. history.replaceState(null, null, url);
  657. }
  658. }, 250);
  659. });
  660. }
  661. dlg("Page remember actived.");
  662. });
  663. }
  664. };
  665. let animationGoToTop = {
  666. "runcase": () => { return MExt.ValueStorage.get("animationGoToTop") },
  667. "config": [{
  668. "id": "animateGoToTopButton",
  669. "default": true,
  670. "name": "回到顶部按钮美化",
  671. "type": "check",
  672. "desc": "为右侧回到顶部按钮增加动画以及位置修正."
  673. }],
  674. "style": `#scrolltop {
  675. bottom: 270px!important;
  676. visibility: visible;
  677. overflow-x: hidden;
  678. width: 75px;
  679. }
  680.  
  681. .scrolltopa {
  682. transition-duration: .15s;
  683. margin-left: -40px;
  684. opacity: 0;
  685. }
  686.  
  687. .scrolltopashow {
  688. margin-left: 0px;
  689. opacity: 1;
  690. }`,
  691. "core": () => {
  692. unsafeWindow.showTopLink = () => {
  693. let ft = $('#ft')[0];
  694. if (ft) {
  695. let scrolltop = $('#scrolltop')[0];
  696. if (!scrolltop) {
  697. return false;
  698. }
  699. let scrolltopbtn = $(".scrolltopa");
  700. let scrollHeight = parseInt(document.body.getBoundingClientRect().top);
  701. let basew = parseInt(ft.clientWidth);
  702. let sw = scrolltop.clientWidth;
  703. if (basew < 1000) {
  704. let left = parseInt(fetchOffset(ft)['left']);
  705. left = left < sw ? left * 2 - sw : left;
  706. scrolltop.style.left = (basew + left + 44) + 'px';
  707. } else {
  708. scrolltop.style.left = 'auto';
  709. scrolltop.style.right = 0;
  710. }
  711. if (scrollHeight < -100) {
  712. scrolltopbtn.addClass("scrolltopashow");
  713. } else {
  714. scrolltopbtn.removeClass("scrolltopashow");
  715. }
  716. }
  717. }
  718. showTopLink();
  719. }
  720. };
  721. let pinnerTopBar = {
  722. "runcase": () => { return MExt.ValueStorage.get("pinnedTopBar") },
  723. "config": [{
  724. "id": "pinnedTopBar",
  725. "default": true,
  726. "name": "更好的固定顶栏",
  727. "type": "check",
  728. "desc": "优化固定顶栏的行为,如与编辑栏的兼容性,以及在极窄窗口下的显示."
  729. }],
  730. "style": `#toptb {
  731. position: fixed;
  732. width: 100%;
  733. z-index: 790;
  734. top: 0;
  735. box-shadow: rgba(0, 0, 0, 0.3) 3px 3px 5px 1px;
  736. min-width: 510px;
  737. }
  738.  
  739. .new_wp {
  740. max-width: 1130px;
  741. width: 100%;
  742. }
  743.  
  744. .mc_map_wp {
  745. padding-top: 45px;
  746. }
  747.  
  748. .mw {
  749. padding-top: 60px
  750. }
  751.  
  752. #user_info_menu, #myprompt_menu, #usertools_menu, #sslct_menu, #scbar_type_menu {
  753. position: fixed!important;
  754. top: 47px!important
  755. }
  756.  
  757. #scbar_type_menu {
  758. top: 38px!important;
  759. }
  760.  
  761. #e_controls {
  762. z-index: 790!important
  763. }
  764.  
  765. @media screen and (max-width: 860px) {
  766. #toptb .z.light {
  767. display: none;
  768. }
  769. #toptb>.new_wp>.y {
  770. float: none;
  771. margin-left: 12px;
  772. }
  773. }`,
  774. "core": () => {
  775. $(() => {
  776. // 重写editorcontrolpos函数,与固定顶栏兼容
  777. editorcontrolpos = () => {
  778. if (editorisfull) {
  779. return;
  780. }
  781. let scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
  782. if (scrollTop + 47 > editorcontroltop && editorcurrentheight > editorminheight) {
  783. $("#" + editorid + '_controls').prop("style", "z-index:0!important").css("position", 'fixed').css("top", '47px').css("width", editorcontrolwidth + 'px');
  784. $("#" + editorid + '_controls_mask').css("display", '');
  785. } else {
  786. $("#" + editorid + '_controls').css("position", '').css('top', '').css('width', '');
  787. $("#" + editorid + '_controls_mask').css('display', 'none');
  788. }
  789. };
  790. //增加一个5px的遮罩,防止鼠标经过空隙时碰到底层内容
  791. $("#toptb").after('<div style="position: fixed;top: 47px;height: 5px;width: 100%;z-index:700;"></div>');
  792. dlg("Mask appended.");
  793. });
  794. }
  795. };
  796. let fixTopBarPopMenu = {
  797. "runcase": () => { return MExt.ValueStorage.get("fixTopBarPopMenu") },
  798. "config": [{
  799. "id": "fixTopBarPopMenu",
  800. "default": true,
  801. "type": "check",
  802. "name": "弹出菜单美化",
  803. "desc": "美化弹出菜单的样式,如个人信息菜单."
  804. }],
  805. "style": `.p_pop:not(.blk) a {
  806. border-radius: 5px;
  807. border-bottom: none;
  808. }
  809.  
  810. div#user_info_menu {
  811. margin-top: 5px;
  812. }
  813.  
  814. .user_info_menu_info>li {
  815. margin-top: 2px;
  816. }
  817.  
  818. a.rank {
  819. padding: 2px 7px!important;
  820. border-radius: 14px;
  821. }
  822.  
  823. a.rank:hover {
  824. text-decoration: none;
  825. }
  826.  
  827. ul.user_info_menu_btn {
  828. padding-top: 6px;
  829. }
  830.  
  831. ul.user_info_menu_btn>li>a:hover {
  832. background:
  833.  
  834. }
  835.  
  836. ul.user_info_menu_btn>li>a {
  837. padding: 5px 8px;
  838. border-radius: 5px;
  839. }
  840.  
  841. ul.user_info_menu_btn>li>a[onclick]:hover {
  842. background: red!important;
  843. }
  844.  
  845. #myprompt_menu {
  846. margin-left: -10px;
  847. }
  848.  
  849. #myprompt_menu, #usertools_menu, #sslct_menu {
  850. z-index: 791!important;
  851. margin-top: 5px!important;
  852. transform: translateX(-50%);
  853. margin-left: 20px;
  854. }
  855.  
  856. .p_pop:not(.h_pop) {
  857. border: 1px solid #d1d1d1;
  858. min-width: unset;
  859. border-radius: 5px;
  860. }
  861.  
  862. #myprompt_menu>li>a, #usertools_menu>li>a, #scbar_type_menu>li>a {
  863. border: none;
  864. border-radius: 5px;
  865. text-align: center;
  866. padding: 3px 15px;
  867. }
  868.  
  869. #myprompt_menu>li>a:hover, #scbar_type_menu>li>a:hover, #usertools_menu>li>a:hover {
  870. background: #36b030;
  871. color: white;
  872. }
  873.  
  874. div#sslct_menu {
  875. margin-left: 54px;
  876. padding-left: 14px;
  877. }
  878.  
  879. .sslct_btn {
  880. border: none!important;
  881. width: 15px;
  882. height: 15px;
  883. padding: 2px;
  884. }
  885.  
  886. .sslct_btn i {
  887. border-radius: 50%;
  888. width: 13px;
  889. height: 13px;
  890. }
  891.  
  892. #scbar_type_menu {
  893. background: url(https://www.mcbbs.net/template/mcbbs/image/bg-wool-white.png);
  894. }
  895.  
  896. a#scbar_type:after {
  897. content: "▼";
  898. margin-left: 10px;
  899. }
  900.  
  901. #scbar_type_menu>li>a {
  902. padding: 3px 5px;
  903. line-height: 20px;
  904. height: 20px;
  905. }
  906.  
  907. .scbar_type_td {
  908. background: url(https://www.mcbbs.net/template/mcbbs/image/scbar_txt.png) -95px center no-repeat
  909. }
  910.  
  911. .y_search {
  912. width: 249px;
  913. border-radius: 3px;
  914. overflow: hidden;
  915. }
  916. .y_search_inp {
  917. float: unset;
  918. }
  919.  
  920. #scbar_txt {
  921. width: 130px;
  922. background-color: transparent;
  923. }
  924. body.winter{
  925. --MExtBtnClr: #5c8dff!important;
  926. }
  927. body.nether{
  928. --MExtBtnClr: #a42e0b!important;
  929. }
  930. body{
  931. --MExtBtnClr: #36b030!important;
  932. }
  933. .user_info_menu_info li a.rank, .user_info_menu_info li a.rank font, ul.user_info_menu_btn>li>a:hover, .p_pop:not(.blk) a:hover,#myprompt_menu>li>a:hover, #scbar_type_menu>li>a:hover, #usertools_menu>li>a:hover, .p_pop:not(.blk) a:hover {
  934. background: var(--MExtBtnClr);
  935. color: white!important;
  936. }
  937.  
  938. `,
  939. "core": () => {
  940. let __extstyle = extstyle;
  941. let checkStyle = (style = null) => {
  942. let theme = style == null ? getcookie('extstyle') : style;
  943. if (theme == "./template/mcbbs/style/winter") {
  944. $("body").removeClass("nether").addClass("winter");
  945. } else if (theme == "./template/mcbbs/style/default") {
  946. $("body").removeClass("winter nether");
  947. } else {
  948. $("body").addClass("nether").removeClass("winter");
  949. }
  950. }
  951. extstyle = (style) => {
  952. __extstyle(style);
  953. checkStyle(style);
  954. }
  955. checkStyle();
  956. }
  957. };
  958. let hoverableMesdal = {
  959. "runcase": () => { return MExt.ValueStorage.get("hoverableMedal") },
  960. "config": [{
  961. "id": "hoverableMedal",
  962. "default": true,
  963. "name": "玻璃质感勋章",
  964. "type": "check",
  965. "desc": "亮闪闪的勋章~"
  966. }],
  967. "style": `.hoverable-medal:hover:after {
  968. margin-top: 0px!important;
  969. opacity: 1!important;
  970. }
  971.  
  972. .hoverable-medal:after {
  973. display: block;
  974. content: '';
  975. margin-top: -15px;
  976. opacity: 0.6;
  977. transition-duration: .4s;
  978. background-image: url(` + staticRes.medalReflectImage + `);
  979. width: 100%;
  980. height: 100%;
  981. filter: blur(2px);
  982. }
  983.  
  984. div.tip.tip_4[id*=md_] {
  985. width: 105px;
  986. height: 165px;
  987. border: none;
  988. box-shadow: black 0px 2px 10px -3px;
  989. margin-left: 38px;
  990. margin-top: 115px;
  991. background: black;
  992. overflow: hidden;
  993. pointer-events: none!important;
  994. border-radius: 5px;
  995. padding: 0px;
  996. }
  997.  
  998. div.tip.tip_4[id*=md_] .tip_horn {
  999. background-size: cover;
  1000. background-position: center;
  1001. height: 200%;
  1002. width: 200%;
  1003. z-index: -1;
  1004. filter: blur(7px) brightness(0.8);
  1005. top: -50%;
  1006. left: -50%;
  1007. }
  1008.  
  1009. div.tip.tip_4[id*=md_] .tip_c {
  1010. color: rgba(255, 255, 255, 0.98);
  1011. }
  1012.  
  1013. div.tip.tip_4[id*=md_] h4 {
  1014. text-align: center;
  1015. padding: 10px 5px;
  1016. background-color: rgba(255, 255, 255, 0.3);
  1017. }
  1018.  
  1019. div.tip.tip_4[id*=md_] p {
  1020. padding: 0px 10px;
  1021. position: absolute;
  1022. top: calc(50% + 38px);
  1023. transform: translateY(calc(-50% - 26px));
  1024. }
  1025.  
  1026. .md_ctrl {
  1027. margin-left: 17px!important;
  1028. padding-bottom: 15px;
  1029. }
  1030.  
  1031. .hoverable-medal {
  1032. width: 31px;
  1033. height: 53px;
  1034. transition-duration: 0.4s;
  1035. border-radius: 3px;
  1036. display: inline-block;
  1037. margin: 5px;
  1038. background-position: center;
  1039. box-shadow: 0px 2px 5px 0px black;
  1040. overflow: hidden;
  1041. }
  1042.  
  1043. .hoverable-medal:hover {
  1044. transform: matrix3d(1, 0, 0, 0, 0, 1, 0, -0.003, 0, 0, 1, 0, 0, -1.5, 0, 0.9);
  1045. box-shadow: 0px 2px 10px -3px black;
  1046. }
  1047.  
  1048. .pg_medal .mgcl img {
  1049. margin-top: 12px!important
  1050. }
  1051.  
  1052. .mg_img {
  1053. box-shadow: inset 0 0 10px 4px rgba(0, 0, 0, 0.3);
  1054. border-radius: 5px;
  1055. }
  1056. .md_ctrl:not([glassmedal]){
  1057. display:none;
  1058. }`,
  1059. "core": () => {
  1060. let rewriteMedal = () => {
  1061. // 遍历所有未重写楼层
  1062. $('.md_ctrl:not([glassmedal])').attr("glassmedal", "true").each((t, v) => {
  1063. // 遍历楼层所有勋章
  1064. $(v).children(0).children('img').each((b, n) => {
  1065. // 获得勋章ID
  1066. let id = 'md' + /\_\d*$/.exec(n.id)[0];
  1067. // 重写勋章结构
  1068. $(v).append(
  1069. $('<span class="hoverable-medal" id="' + n.id + '" style="background-image:url(' + n.src + ')"></span>').on('mouseover', () => {
  1070. showMenu({
  1071. 'ctrlid': n.id,
  1072. 'menuid': id + '_menu',
  1073. 'pos': '12!'
  1074. });
  1075. })
  1076. );
  1077. // 重写提示样式
  1078. $("#" + id + "_menu .tip_horn").css("background-image", "url(" + n.src + ")");
  1079. // 移除旧的勋章
  1080. n.remove();
  1081. });
  1082. });
  1083. };
  1084. //调用重写勋章函数
  1085. $(rewriteMedal);
  1086. // 在Ajax时重新调用Ajax函数,保存勋章样式
  1087. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", rewriteMedal);
  1088. }
  1089. };
  1090. let viewWarns = {
  1091. "runcase": () => { return MExt.ValueStorage.get("viewWarns") },
  1092. "config": [{
  1093. "id": "viewWarns",
  1094. "default": true,
  1095. "name": "查看警告记录",
  1096. "type": "check",
  1097. "desc": "为每一层楼和每一个个人主页(除自己)添加查看警告记录按钮"
  1098. }],
  1099. "style": `.view_warns_inposts {
  1100. background: url(template/mcbbs/image/warning.gif) no-repeat 0px 2px;
  1101. background-size: 16px;
  1102. width: 90px!important;
  1103. }
  1104.  
  1105. .view_warns_home a {
  1106. background: url(template/mcbbs/image/warning.gif) no-repeat 1px 2px!important;
  1107. background-size: 16px!important;
  1108. }`,
  1109. "core": () => {
  1110. let addVWLink = () => {
  1111. $(".plhin:not([vw-added*=true])").each((i, v) => {
  1112. let href = $(v).find(".authi .xw1").attr("href");
  1113. if (!href) {
  1114. return false;
  1115. }
  1116. let uid = /uid=(\d*)/.exec(href)[1];
  1117. $(v).attr("vw-added", "true").find("ul.xl.xl2.o.cl").append($('<li class="view_warns_inposts"><a href="forum.php?mod=misc&action=viewwarning&tid=952104&uid=' + uid + '" title="查看警告记录" class="xi2" onclick="showWindow(\'viewwarning\', this.href)">查看警告记录</a></li>'));
  1118. });
  1119. dlg("In-posts view warns link added");
  1120. }
  1121. // 在DiscuzAjax时重新调用添加函数,防止失效
  1122. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", addVWLink);
  1123. dlg("add VWLink Ajax Event attached.");
  1124. $(() => {
  1125. // 添加查看警告按钮
  1126. addVWLink();
  1127. // 用户信息界面添加查看警告按钮
  1128. let href = $("#uhd .cl a").attr("href");
  1129. if (!href) {
  1130. return false;
  1131. }
  1132. let uid = /uid=(\d*)/.exec(href)[1];
  1133. if (!uid) {
  1134. return false;
  1135. }
  1136. $("#uhd .mn ul").append('<li class="view_warns_home"><a href="forum.php?mod=misc&action=viewwarning&tid=952104&uid=' + uid + '" title="查看警告记录" class="xi2" onclick="showWindow(\'viewwarning\', this.href)">查看警告记录</a></li>');
  1137. dlg("Home page view warns link added.")
  1138. });
  1139. }
  1140. };
  1141. let removeLinkWarn = {
  1142. "runcase": () => { return MExt.ValueStorage.get("removeLinkWarn") && location.pathname == "/plugin.php" && MExt.Units.getRequest('id') == "link_redirect" },
  1143. "config": [{
  1144. "id": "removeLinkWarn",
  1145. "default": true,
  1146. "name": "移除外链警告",
  1147. "type": "check",
  1148. "desc": "去除论坛跳转外链时的警告页面."
  1149. }],
  1150. "core": () => {
  1151. let url = MExt.Units.getRequest('target');
  1152. if (url) {
  1153. // 跳就完事了
  1154. location.href = decodeURIComponent(url);
  1155. }
  1156. }
  1157. };
  1158. let useIgInQuickReply = {
  1159. "runcase": () => { return MExt.ValueStorage.get("useIgInQuickReply") },
  1160. "config": [{
  1161. "id": "useIgInQuickReply",
  1162. "default": true,
  1163. "name": "快速回复使用个人签名",
  1164. "type": "check",
  1165. "desc": "在页脚快速回复帖子时使用个人签名."
  1166. }],
  1167. "core": () => {
  1168. // 快速回复框使用个人签名
  1169. let hookReplyBtn = () => {
  1170. if ($("#fwin_reply #usesig").length > 0) { return false; }
  1171. $("#fwin_reply #postsubmit").after('<label for="usesig" style="margin-left: 10px;float: left;margin-top: 3px;"><input type="checkbox" name="usesig" id="usesig" class="pc" value="1" checked="checked">使用个人签名</label>');
  1172. dlg("Use Ig Checkbox appended.");
  1173. }
  1174. $("#append_parent").on('DOMNodeInserted', hookReplyBtn);
  1175. $(() => {
  1176. // 底部快速回复增加选项
  1177. $("#fastpostsubmit").after('<label for="usesig" style="margin-left: 10px;"><input type="checkbox" name="usesig" id="usesig" class="pc" value="1" checked="checked">使用个人签名</label>');
  1178. });
  1179. }
  1180. };
  1181. let fixImgZoom = {
  1182. "runcase": () => { return MExt.ValueStorage.get("fixImgZoom") },
  1183. "config": [{
  1184. "id": "fixImgZoom",
  1185. "default": true,
  1186. "name": "优化图片缩放",
  1187. "type": "check",
  1188. "desc": "使用更现代的方法实现图片缩放."
  1189. }],
  1190. "style": `#img_scale {
  1191. opacity: 0;
  1192. position: absolute;
  1193. right: 20px;
  1194. bottom: 20px;
  1195. background: #0006;
  1196. transition-duration: .2s;
  1197. color: white;
  1198. padding: 10px;
  1199. pointer-events: none;
  1200. border-radius: 10px;
  1201. }
  1202.  
  1203. #imgzoom_zoom {
  1204. height: auto;
  1205. transition-duration: .2s
  1206. }
  1207.  
  1208. #imgzoom_zoomlayer {
  1209. height: auto!important
  1210. }
  1211.  
  1212. #imgzoom {
  1213. width: auto!important;
  1214. height: auto!important
  1215. }`,
  1216. "core": () => {
  1217. let __zoom = zoom;
  1218. let t = 0;
  1219. // 初始化基本缩放信息对象
  1220. let img = { width: 0, height: 0, top: 0, left: 0, radio: 1, scale: 1, orgwidth: 0 };
  1221. // 缩放函数
  1222. let resize = (width) => {
  1223. dlg("Image resizing...")
  1224. clearTimeout(t);
  1225. // 显示缩放比例
  1226. $("#img_scale").html(parseInt(img.scale * 100) + "%").css("opacity", 1);
  1227. t = setTimeout(() => { $("#img_scale").css("opacity", 0) }, 2000);
  1228. // 计算目标大小和位置
  1229. let ow = img.width;
  1230. img.width = width;
  1231. ow = (ow - img.width) / -2;
  1232. img.left -= ow;
  1233. img.top -= ow * img.radio;
  1234. // 修改
  1235. $("#imgzoom_zoom").css("width", img.width + "px");
  1236. $("#imgzoom").css("left", img.left + "px");
  1237. $("#imgzoom").css("top", img.top + "px");
  1238. }
  1239. // 保存基本信息
  1240. let initP = () => {
  1241. dlg("Init Picture info");
  1242. img.width = parseInt($("#imgzoom_zoom").attr("width"));
  1243. img.height = parseInt($("#imgzoom_zoom").attr("height"));
  1244. img.radio = img.height / img.width;
  1245. img.top = parseInt($("#imgzoom").css("top"));
  1246. img.left = parseInt($("#imgzoom").css("left"));
  1247. img.scale = 1;
  1248. img.orgwidth = img.width;
  1249. }
  1250. zoom = (obj, zimg, nocover, pn, showexif) => {
  1251. // 伪装成IE,使原函数的DOMMouseScroll事件监听器以可以被卸除的形式添加
  1252. BROWSER.ie = 6;
  1253. __zoom(obj, zimg, nocover, pn, showexif);
  1254. // 防止翻车,改回去
  1255. setTimeout(() => {
  1256. BROWSER.ie = 0;
  1257. dlg("IE canceled.")
  1258. }, 1000);
  1259. // 等待窗口出现
  1260. let wait = setInterval(() => {
  1261. if ($("#imgzoom_zoom").length) {
  1262. dlg("Image found");
  1263. clearInterval(wait);
  1264. // 信息归零,准备下一次保存
  1265. img = { width: 0, height: 0, top: 0, left: 0, radio: 1, scale: 1, orgwidth: 0 };
  1266. // 显示遮罩
  1267. $("#imgzoom_cover").css("display", "unset");
  1268. // 判断是否已经监听事件,防止超级加倍
  1269. if ($("#imgzoom").attr("fixed") == "true") { return true; }
  1270. // 原始尺寸按钮事件
  1271. $("#imgzoom_adjust").on("click", () => {
  1272. dlg("return source size");
  1273. $("#imgzoom").css("transition-property", "opacity,top,left,transform");
  1274. img.width == 0 ? initP() : 0;
  1275. img.scale = 1;
  1276. resize($("#imgzoom_zoom").attr("width"));
  1277. });
  1278. // 屏蔽页面滚动
  1279. $("#imgzoom_cover").on("mousewheel DOMMouseScroll", (e) => {
  1280. if (e.ctrlKey || e.altKey || e.shiftKey) { return true; }
  1281. e.preventDefault();
  1282. });
  1283. // 卸除原函数监听器
  1284. $("#imgzoom")[0].onmousewheel = null;
  1285. // 增加显示缩放大小元素并监听事件
  1286. $("#imgzoom").append(`<span id="img_scale"></span>`).on("mousewheel DOMMouseScroll", (e) => {
  1287. // 判断是否按下功能键
  1288. if (e.ctrlKey || e.altKey || e.shiftKey) { dlg("Func key pressed."); return true; }
  1289. // 阻止滚动
  1290. e.preventDefault();
  1291. // 兼容火狐,正确判断滚轮方向
  1292. let scroll = e.originalEvent.wheelDelta ? e.originalEvent.wheelDelta : -e.originalEvent.detail;
  1293. // 忽略无效滚动
  1294. if (scroll == 0) { return true; }
  1295. // 判断是否需要初始化
  1296. img.width == 0 ? initP() : 0;
  1297. // 规定需要显示过渡动画的属性
  1298. $("#imgzoom").css("transition-property", "opacity,top,left,transform");
  1299. // 判断是否过小
  1300. if (scroll < 0 && ((img.width < 350 && img.radio < 1) || (img.width * img.radio < 350 && img.radio >= 1))) {
  1301. // 回弹动画
  1302. dlg("Reach min size");
  1303. $("#imgzoom").css("transform", "scale(0.8)");
  1304. setTimeout(() => { $("#imgzoom").css("transform", "scale(1)"); }, 200);
  1305. return true;
  1306. }
  1307. // 修改缩放比例
  1308. img.scale += scroll > 0 ? 0.1 : -0.1;
  1309. // 判断比例是否过小
  1310. if (img.scale < 0.1) {
  1311. img.scale = 0.1;
  1312. // 回弹动画
  1313. dlg("Reach min size");
  1314. $("#imgzoom").css("transform", "scale(0.8)");
  1315. setTimeout(() => { $("#imgzoom").css("transform", "scale(1)"); }, 200);
  1316. return true;
  1317. }
  1318. // 缩放
  1319. resize(img.orgwidth * Math.pow(img.scale, 2));
  1320. }).attr("fixed", "true");
  1321. // 按下鼠标事件
  1322. $("#imgzoom").on("mousedown", (e) => {
  1323. // 按下鼠标时移除修改位置的过渡动画,使窗口跟手
  1324. dlg("Animate removed");
  1325. $("#imgzoom").css("transition-property", "opacity");
  1326. });
  1327. // 释放鼠标事件
  1328. $("#imgzoom").on("mouseup", (e) => {
  1329. // 改回去
  1330. $("#imgzoom").css("transition-property", "opacity,top,left,transform");
  1331. // 保存移动后的窗口位置
  1332. img.top = parseInt($("#imgzoom").css("top"));
  1333. img.left = parseInt($("#imgzoom").css("left"));
  1334. dlg("Animate added,Pos saved");
  1335. });
  1336. }
  1337. }, 50);
  1338. }
  1339. }
  1340. }
  1341. let disableAutoplay = {
  1342. "runcase": () => { return MExt.ValueStorage.get("disableAutoplay") },
  1343. "config": [{
  1344. "id": "disableAutoplay",
  1345. "default": false,
  1346. "name": "禁止BGM自动播放",
  1347. "type": "check",
  1348. "desc": "阻止页内BGM自动播放."
  1349. }],
  1350. "core": () => {
  1351. let clearAutoPlay = () => {
  1352. $("iframe[id*=iframe_mp3]:not([id*=no_autoplay])").each((i, v) => {
  1353. // 重构播放器,去除自动播放属性
  1354. let player = document.createElement("iframe");
  1355. let hidden = document.createElement("div");
  1356. hidden.id = v.id;
  1357. hidden.style.display = "none";
  1358. player.id = v.id + "_no_autoplay";
  1359. player.width = v.width;
  1360. player.height = v.height;
  1361. player.frameBorder = v.frameBorder;
  1362. player.allow = v.allow;
  1363. player.src = v.src.replace("&auto=1", "");
  1364. v.after(hidden);
  1365. v.after(player);
  1366. v.remove();
  1367. dlg("Canceled all autoplay");
  1368. });
  1369. };
  1370. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", () => { setTimeout(clearAutoPlay, 100); });
  1371. $(clearAutoPlay);
  1372. }
  1373. };
  1374. let rememberEditorMode = {
  1375. "runcase": () => { return MExt.ValueStorage.get("remenberEditMode") },
  1376. "config": [{
  1377. "id": "remenberEditMode",
  1378. "default": true,
  1379. "name": "记忆编辑器模式",
  1380. "type": "check",
  1381. "desc": "记忆高级编辑器是纯文本模式还是即时模式."
  1382. }],
  1383. "core": () => {
  1384. if (localStorage.getItem("MExt_EditMode") === null) {
  1385. localStorage.setItem("MExt_EditMode", "false");
  1386. }
  1387. $(() => {
  1388. dlg("Remenber Editor Mode actived.");
  1389. $("#e_switchercheck").on("click", (e) => {
  1390. dlg("Editor mode switch.");
  1391. localStorage.setItem("MExt_EditMode", e.currentTarget.checked.toString());
  1392. });
  1393. if (localStorage.getItem("MExt_EditMode") == "true") {
  1394. dlg("Switch editor mode");
  1395. $("#e_switchercheck").click();
  1396. }
  1397. });
  1398. }
  1399. };
  1400. let highlightThreads = {
  1401. "runcase": () => { return MExt.ValueStorage.get("highlightThreads") },
  1402. "config": [{
  1403. "id": "highlightThreads",
  1404. "default": true,
  1405. "name": "帖子列表高亮",
  1406. "type": "check",
  1407. "desc": "列表高亮显示帖子类型."
  1408. }],
  1409. "style": `.tl .icn {
  1410. background-color: rgba(200, 200, 200, 0.3)!important;
  1411. background-image: linear-gradient(-90deg, rgb(251 242 219), transparent);
  1412. border-left: 3px solid rgb(200, 200, 200);
  1413. transition-duration: .2s;
  1414. }
  1415. .tl .icn.newReply {
  1416. background-color: rgba(255, 136, 0, 0.3)!important;
  1417. border-left: 3px solid rgb(255, 136, 0);
  1418. }
  1419.  
  1420. .tl .icn.newMember {
  1421. background-color: rgba(110, 232, 115, 0.3)!important;
  1422. border-left: 3px solid rgb(110, 232, 115);
  1423. }
  1424.  
  1425. .tl .icn.hotThread {
  1426. background-color: rgba(235, 132, 132, 0.3)!important;
  1427. border-left: 3px solid rgb(235, 132, 132);
  1428. }
  1429.  
  1430. .tl .icn.digest {
  1431. background-color: rgba(0, 203, 214, 0.3)!important;
  1432. border-left: 3px solid rgb(0, 203, 214);
  1433. }
  1434.  
  1435. .tl .icn.digest2 {
  1436. background-color: rgba( 0, 161, 204, 0.3)!important;
  1437. border-left: 3px solid rgb( 0, 161, 204);
  1438. }
  1439.  
  1440. .tl .icn.digest3 {
  1441. background-color: rgba(0, 123, 194, 0.3)!important;
  1442. border-left: 3px solid rgb(0, 123, 194);
  1443. }
  1444.  
  1445. .tl .icn.close {
  1446. background-color: rgba(187, 187, 187, 0.3)!important;
  1447. border-left: 3px solid rgb(187, 187, 187);
  1448. }
  1449.  
  1450. .tl .icn.forumSticker {
  1451. background-color: rgba(161, 215, 252, 0.3)!important;
  1452. border-left: 3px solid rgb(161, 215, 252);
  1453. }
  1454.  
  1455. .tl .icn.partSticker {
  1456. background-color: rgba(110, 171, 235, 0.3)!important;
  1457. border-left: 3px solid rgb(110, 171, 235);
  1458. }
  1459.  
  1460. .tl .icn.globalSticker {
  1461. background-color: rgba(33, 106, 207, 0.3)!important;
  1462. border-left: 3px solid rgb(33, 106, 207);
  1463. }
  1464.  
  1465. .tl .icn.poll {
  1466. background-color: rgba(250, 123, 147, 0.3)!important;
  1467. border-left: 3px solid rgb(250, 123, 147);
  1468. }
  1469.  
  1470. .tl .icn.debate {
  1471. background-color: rgba(0, 153, 204, 0.3)!important;
  1472. border-left: 3px solid rgb(0, 153, 204);
  1473. }`,
  1474. "core": () => {
  1475. let highlighting = () => {
  1476. $('#moderate a[title*="有新回复"]').parent().addClass("newReply");
  1477. $('#moderate img[alt="新人帖"]').parent().parent().children(".icn").addClass("newMember");
  1478. $('#moderate img[alt="热帖"]').parent().parent().children(".icn").addClass("hotThread");
  1479. //精华
  1480. $('#moderate img[alt="digest"]').parent().parent().children(".icn").addClass("digest");
  1481. $('#moderate img[title="精华 2"]').parent().parent().children(".icn").addClass("digest2");
  1482. $('#moderate img[title="精华 3"]').parent().parent().children(".icn").addClass("digest3");
  1483. $('#moderate a[title*="关闭的主题"]').parent().addClass("close");
  1484. $('#moderate a[title*="本版置顶主题"]').parent().addClass("forumSticker");
  1485. $('#moderate a[title*="分类置顶主题"]').parent().addClass("partSticker");
  1486. $('#moderate a[title*="全局置顶主题"]').parent().addClass("globalSticker");
  1487. $('#moderate a[title*="辩论"]').parent().addClass("debate");
  1488. $('#moderate a[title*="投票"]').parent().addClass("poll");
  1489. $('#moderate a[title*="悬赏"]').parent().addClass("newReply");
  1490. $('#moderate a.s.xst[style*=color]').each((i, v) => {
  1491. const style = v.parentNode.parentNode.querySelector(".icn").style;
  1492. style.setProperty("background-color", v.style.color.replace(")", ",0.4)").replace("rgb(", "rgba("), "important");
  1493. style.borderLeftColor = v.style.color;
  1494. });
  1495. dlg("Thread list highlighting done.");
  1496. };
  1497. $(highlighting);
  1498. let waiter = 0;
  1499. $(() => {
  1500. let nxBtn = $("#autopbn");
  1501. nxBtn.on("click", () => {
  1502. if (waiter == 0) {
  1503. waiter = setInterval(() => {
  1504. if (nxBtn.text() != "正在加载, 请稍后...") {
  1505. clearInterval(waiter);
  1506. waiter = 0;
  1507. highlighting();
  1508. }
  1509. }, 100);
  1510. }
  1511. });
  1512. });
  1513. }
  1514. };
  1515. let fixAnchor = {
  1516. "runcase": () => { return MExt.ValueStorage.get("fixAnchor") },
  1517. "config": [{
  1518. "id": "fixAnchor",
  1519. "default": false,
  1520. "name": "帖内锚点修复",
  1521. "type": "check",
  1522. "desc": "防止帖内锚点被意外的赋予样式."
  1523. }],
  1524. "style": `table.plhin td.t_f span[id]:not([id^=anchor-]), .fastpreview span[id]:not([id^=anchor-]) {
  1525. display: none!important
  1526. }`,
  1527. "core": () => {
  1528. let lastHash = null;
  1529. let handleAnchorJump = () => {
  1530. if(!location.hash || location.hash.substr(0,1) !== "#" || lastHash === location.hash) return;
  1531. lastHash = location.hash;
  1532. const hash = lastHash.substr(1);
  1533. if (hash.length == 0) return;
  1534. const offset = $(`span#anchor-${hash}`).offset();
  1535. const body = unsafeWindow.document.scrollingElement;
  1536. if (!offset) return;
  1537. $(body).animate({
  1538. scrollTop: offset.top - 48
  1539. }, 300);
  1540. };
  1541. let fix = () => {
  1542. $("table.plhin td.t_f span[id]:not([id^=anchor-]), .fastpreview .bm_c div[id^=post_] span[id]:not([id^=anchor-])").each((i, v) => {
  1543. v.id = "anchor-" + v.id;
  1544. });
  1545. handleAnchorJump();
  1546. dlg('Anchor fixed.');
  1547. };
  1548. $(fix);
  1549. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", fix).on("hashchange", handleAnchorJump);
  1550. }
  1551. };
  1552. let replaceFlash = {
  1553. "runcase": () => { return MExt.ValueStorage.get("replaceFlash") },
  1554. "config": [{
  1555. "id": "replaceFlash",
  1556. "default": true,
  1557. "name": "Flash播放器替换",
  1558. "type": "check",
  1559. "desc": "将网易云Flash播放器替换成H5播放器."
  1560. }],
  1561. "core": () => {
  1562. let replace = () => {
  1563. $("span[id*=swf] embed").each((i, v) => {
  1564. let player = document.createElement("iframe");
  1565. if(v.src.indexOf("style/swf/widget.swf") == -1){
  1566. return;
  1567. }
  1568. player.src = v.src.replace("style/swf/widget.swf", "outchain/player").replace("sid=", "id=");
  1569. player.width = v.width;
  1570. player.height = v.height;
  1571. player.frameBorder = "no";
  1572. player.allow = "autoplay; fullscreen";
  1573. player.id = v.parentElement.id + "_no_autoplay";
  1574. v.parentElement.after(player);
  1575. v.parentElement.remove();
  1576. });
  1577. }
  1578. $(replace);
  1579. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", replace);
  1580. }
  1581. };
  1582. let restrictMedalLine = {
  1583. "runcase": () => { return MExt.ValueStorage.get("maxMedalLine") >= 0 },
  1584. "config": [{
  1585. "id": "maxMedalLine",
  1586. "default": -1,
  1587. "type": "num",
  1588. "name": "最大勋章行数",
  1589. "desc": "限制楼层勋章的最大行数,提升鼠标滚轮寿命,设置为-1以禁用此功能."
  1590. }],
  1591. "style": `.md_ctrl span.toggle-all {
  1592. width: 125px;
  1593. display: block;
  1594. position: absolute;
  1595. bottom: 0;
  1596. text-align: center;
  1597. left: 0;
  1598. padding: 30px 0px 5px 0px;
  1599. background-image: linear-gradient(0deg, #e3c99e, #e3c99e, transparent);
  1600. color: #3e6c99;
  1601. cursor: pointer;
  1602. user-select: none;
  1603. }
  1604.  
  1605. .md_ctrl {
  1606. position: relative;
  1607. overflow-y: hidden;
  1608. max-height: ` + (Stg.get('maxMedalLine') * (Stg.get('hoverableMedal') ? 60 : 55) + 45).toString() + `px!important;
  1609. transition:unset!important;
  1610. }
  1611.  
  1612. .md_ctrl.show-all {
  1613. max-height: 3000px!important;
  1614. padding-bottom: 40px;
  1615. }`,
  1616. "core": () => {
  1617. let restrict = () => {
  1618. // 判断是否在个人主页
  1619. if ($("#uhd").length > 0) { $("#restrictMedalLine").remove(); return; }
  1620. // 限制勋章行数
  1621. dlg("Restricting line...");
  1622. $('.md_ctrl:not([restrictline])').attr("restrictline", "true").append($("<span class=\"toggle-all\">展开/收起勋章</span>").on("click", (e) => { $(e.target).parent().toggleClass("show-all") })).each((i, v) => {
  1623. if ((v.childElementCount - 2 <= Stg.get('maxMedalLine') * 3 && Stg.get('hoverableMedal')) || (v.firstChild.childElementCount - 2 <= Stg.get('maxMedalLine') * 3 && !Stg.get('hoverableMedal'))) {
  1624. v.removeChild(v.lastChild);
  1625. }
  1626. });
  1627. }
  1628. $(restrict);
  1629. $(this).on("DiscuzAjaxGetFinished DiscuzAjaxPostFinished", restrict);
  1630. }
  1631. };
  1632. let quickAt = {
  1633. "runcase": () => { return MExt.ValueStorage.get("quickAtList").length > 0 },
  1634. "config": [{
  1635. "id": "quickAtList",
  1636. "default": "",
  1637. "name": "快速 @ 列表",
  1638. "type": "text",
  1639. "desc": "按下Ctrl+Shift+A/或者按钮以快速在当前输入框内插入预定义的@用户名代码.用户名之间用\",\"(半角逗号)分隔."
  1640. }],
  1641. "style": `#fastpostatList.in_editorbtn, #postatList {
  1642. background-size: 54px;
  1643. background-position: -23px 3px;
  1644. }
  1645.  
  1646. #fastpostatList, #postatList {
  1647. background-image: url(` + staticRes.atBtnImage + `);
  1648. background-size: 50px;
  1649. background-position: -6px 2px;
  1650. }`,
  1651. "core": () => {
  1652. let getAtCode = () => {
  1653. // 分隔list
  1654. let quickAtList = Stg.get('quickAtList').split(",");
  1655. let atstr = "";
  1656. //拼接@代码
  1657. $(quickAtList).each((i, v) => {
  1658. atstr += "@" + v + " ";
  1659. });
  1660. return atstr;
  1661. }
  1662. // 将函数暴露到全局
  1663. MExt_Func_getAtCode = getAtCode;
  1664. // 监听按键事件
  1665. $(document).on("keydown", (e) => {
  1666. if (e.shiftKey && e.ctrlKey && e.keyCode == 65) {
  1667. // 判断是否在输入框内
  1668. if (($(document.activeElement).prop("nodeName") == "INPUT" && $(document.activeElement).prop("type") == "text")) {
  1669. // 拼接方法插入
  1670. $(document.activeElement).val($(document.activeElement).val() + getAtCode());
  1671. dlg("@ string added");
  1672. } else if ($(document.activeElement).prop("nodeName") == "TEXTAREA") {
  1673. // discuz内建函数插入
  1674. seditor_insertunit('fastpost', getAtCode(), '');
  1675. dlg("@ string added");
  1676. }
  1677. }
  1678. });
  1679. // 高级编辑模式插入@代码
  1680. $(() => {
  1681. if ($("#e_iframe").length) {
  1682. // 由于高级模式的输入框是iFrame,无法直接监听,故再次监听高级输入框的按键事件
  1683. $($("#e_iframe")[0].contentWindow).on("keydown", (e) => {
  1684. if (e.shiftKey && e.ctrlKey && e.keyCode == 65) {
  1685. // 判断是否在输入框内
  1686. if ($(document.activeElement).prop("nodeName") == "IFRAME") {
  1687. //discuz内建函数插入
  1688. insertText(getAtCode());
  1689. dlg("@ string added");
  1690. }
  1691. }
  1692. });
  1693. }
  1694. });
  1695. let hookReplyBtn = () => {
  1696. if ($("#postatList").length > 0) { return false; }
  1697. $("#postat.fat").after('<a id="postatList" href="javascript:;" title="快速@" onclick="seditor_insertunit(\'post\',MExt_Func_getAtCode(), \'\');">快速@</a> ');
  1698. dlg("Reply at bottons appends.");
  1699. }
  1700. $("#append_parent").on('DOMNodeInserted', hookReplyBtn);
  1701. $(() => {
  1702. $("#fastpostat").after('<a id="fastpostatList" href="javascript:;" title="快速@" class="" onclick="seditor_insertunit(\'fastpost\',MExt_Func_getAtCode(), \'\');">快速@</a> ');
  1703. $("#e_adv_s1").append('<a id="fastpostatList" href="javascript:;" title="快速@" class="in_editorbtn" onclick="insertText(MExt_Func_getAtCode());">快速@</a>');
  1704. });
  1705. }
  1706. };
  1707. let miscFix = {
  1708. "runcase": () => { return /^[01]*$/.exec(Stg.get('miscFix')) },
  1709. "config": [{
  1710. "id": "miscFix",
  1711. "default": "",
  1712. "name": "杂项修复",
  1713. "type": "text",
  1714. "desc": "此值用于规定杂项修复的行为,默认值为空,修改为0000000000以关闭全部.错误的值会使该项失效.详情请查阅源码."
  1715. }],
  1716. "style": '',
  1717. "core": () => {
  1718. let fixconf = Stg.get('miscFix').split("");
  1719. let fixlist = [
  1720. // 暗牧悬浮预览
  1721. { "style": ".t_f font[style*=\"background-color:black\"], .t_f font[style*=\"background-color:#000\"] {transition-duration: .3s;transition-delay: .5s;cursor: default;}.t_f font[style*=\"background-color:black\"]:hover, .t_f font[style*=\"background-color:#000\"]:hover {transition-delay: 0s;background-color: transparent!important;}" },
  1722. //增加空方法,用于修复论坛的一个报错.
  1723. { "script": "announcement = () => {};relatekw = ()=>{};" },
  1724. //修复页脚问题
  1725. { "style": ".mc_map_wp{min-height:calc(100vh - 202px)!important;}" },
  1726. //修复用户组页面不对齐的问题
  1727. { "style": ".tdats .tb{margin-top:0px}" },
  1728. // 修复编辑器@超级加倍的问题
  1729. { "script": "$(()=>{if(typeof setEditorEvents != \"undefined\"){let __setEditorEvents = setEditorEvents;setEditorEvents= ()=>{ __setEditorEvents();setEditorEvents=()=>{};}}})" },
  1730. // 允许改变个人签名编辑框大小
  1731. { "style": "#sightmlmessage{resize:vertical;}" },
  1732. // 按住shift点击带有超链接的图片则不打开链接
  1733. { "script": `$(()=>{$("img.zoom").parent().each((i,v)=>{if(v.nodeName=="A"){$(v).on("click",(e)=>{console.log(e);if(e.shiftKey){e.preventDefault();}})}})})` },
  1734. // 修复某些页面书框被撕裂的问题
  1735. { "script": "$(()=>{if(!$('.mc_map_wp .mc_map_border_foot').length){$('.mc_map_border_foot').remove();$('.mc_map_wp').append('<div class=\"mc_map_border_foot\"></div>')}})" },
  1736. // 主动聚焦编辑器iframe,修复报错问题.
  1737. { "script": "$(()=>{if(typeof wysiwyg !='undefined' && wysiwyg){editwin.document.body.focus()};})" },
  1738. // 小提示样式修复
  1739. { "style": ".pc_inner{padding-left:12px}" }
  1740. ];
  1741. let styleContent = "";
  1742.  
  1743. $(fixlist).each((i, v) => {
  1744. if (typeof fixconf[i] == "undefined") { fixconf[i] = "1" }
  1745. if (fixconf[i] === "1") {
  1746. // 拼接样式字符串
  1747. styleContent += fixlist[i].style ? fixlist[i].style : "";
  1748. // 执行脚本
  1749. eval(fixlist[i].script ? fixlist[i].script : "");
  1750. }
  1751. });
  1752. MExt.Units.appendStyle(styleContent);
  1753. }
  1754. };
  1755. let myReportReason = {
  1756. "runcase": () => { return MExt.ValueStorage.get("myReportReason").length > 0 },
  1757. "config": [{
  1758. "id": "myReportReason",
  1759. "default": "",
  1760. "name": "自定义举报理由",
  1761. "type": "textarea",
  1762. "desc": "在举报时提供自定义的举报理由,一行一个理由."
  1763. }],
  1764. "core": () => {
  1765. // 获得举报内容列表函数
  1766. let getReasons = () => {
  1767. // 分隔list
  1768. let reportReason = Stg.get('myReportReason').split("\n");
  1769. let rrstr = "<p class=\"mtn mbn\">";
  1770. //拼接HTML
  1771. $(reportReason).each((i, v) => {
  1772. rrstr += '<label><input type="radio" name="report_select" class="pr" onclick="$(\'report_other\').style.display=\'none\';$(\'report_msg\').style.display=\'none\';$(\'report_message\').value=\'' + v + '\'" value="' + v + '"> ' + v + '</label><br>';
  1773. });
  1774. rrstr += "</p>";
  1775. return rrstr;
  1776. }
  1777. // 举报按钮钩子函数
  1778. let hookReportWin = () => {
  1779. if ($("#report_reasons[appended]").length > 0) { return false; };
  1780. let reportContent = getReasons();
  1781. $("#report_reasons").attr("appended", "true").before(reportContent);
  1782. }
  1783. $("#append_parent").on('DOMNodeInserted', hookReportWin);
  1784. }
  1785. };
  1786. let myCSS = {
  1787. "runcase": () => { return MExt.ValueStorage.get("myCSS").length > 0 },
  1788. "config": [{
  1789. "id": "myCSS",
  1790. "default": "",
  1791. "name": "自定义CSS",
  1792. "type": "textarea",
  1793. "desc": "在框内的CSS会被加载到页面内,可自由发挥."
  1794. }],
  1795. "style": MExt.ValueStorage.get("myCSS")
  1796. };
  1797. let myLinks = {
  1798. "runcase": () => { return MExt.ValueStorage.get("myLinks").length > 0 },
  1799. "config": [{
  1800. "id": "myLinks",
  1801. "default": "",
  1802. "name": "自定义工具菜单链接",
  1803. "type": "textarea",
  1804. "desc": "在右上角\"工具\"菜单里添加自定义的链接,以\"[名称] [链接]\"的格式添加(如\"个人主页 home.php\"),一行一个."
  1805. }],
  1806. "core": () => {
  1807. // 分割
  1808. $(Stg.get('myLinks').split("\n")).each((i, v) => {
  1809. try {
  1810. //判断是否合法
  1811. if (!v.split(" ")[1] || !v.split(" ")[0]) { return true; }
  1812. // 添加
  1813. $(() => { $("#usertools_menu").append('<li><a href="' + v.split(" ")[1] + '">' + v.split(" ")[0] + '</a></li>') });
  1814. } catch (ignore) {}
  1815. });
  1816. }
  1817. };
  1818. MExt.exportModule(fixCodeBlock, queryMessage, rememberPage, animationGoToTop, pinnerTopBar, fixTopBarPopMenu, hoverableMesdal, viewWarns, removeLinkWarn, useIgInQuickReply, fixImgZoom, disableAutoplay, rememberEditorMode,
  1819. highlightThreads, fixAnchor, replaceFlash, restrictMedalLine, quickAt, miscFix, myReportReason, myCSS, myLinks);
  1820. })();

QingJ © 2025

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