CSDN优化

支持PC和手机端、屏蔽广告、优化浏览体验、重定向拦截的Url、自动展开全文、自动展开代码块、全文居中、允许复制内容、去除复制内容的小尾巴、自定义屏蔽元素等

当前为 2024-11-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name CSDN优化
  3. // @namespace https://github.com/WhiteSevs/TamperMonkeyScript
  4. // @version 2024.11.7
  5. // @author WhiteSevs
  6. // @description 支持PC和手机端、屏蔽广告、优化浏览体验、重定向拦截的Url、自动展开全文、自动展开代码块、全文居中、允许复制内容、去除复制内容的小尾巴、自定义屏蔽元素等
  7. // @license GPL-3.0-only
  8. // @icon data:image/png;base64,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
  9. // @supportURL https://github.com/WhiteSevs/TamperMonkeyScript/issues
  10. // @match *://*.csdn.net/*
  11. // @require https://update.greasyfork.org/scripts/494167/1413255/CoverUMD.js
  12. // @require https://fastly.jsdelivr.net/npm/@whitesev/utils@2.5.0/dist/index.umd.js
  13. // @require https://fastly.jsdelivr.net/npm/@whitesev/domutils@1.4.0/dist/index.umd.js
  14. // @require https://fastly.jsdelivr.net/npm/@whitesev/pops@1.8.9/dist/index.umd.js
  15. // @require https://fastly.jsdelivr.net/npm/qmsg@1.2.5/dist/index.umd.js
  16. // @grant GM_deleteValue
  17. // @grant GM_getValue
  18. // @grant GM_info
  19. // @grant GM_registerMenuCommand
  20. // @grant GM_setValue
  21. // @grant GM_unregisterMenuCommand
  22. // @grant GM_xmlhttpRequest
  23. // @grant unsafeWindow
  24. // @run-at document-start
  25. // ==/UserScript==
  26.  
  27. (function (Qmsg, DOMUtils, Utils, pops) {
  28. 'use strict';
  29.  
  30. var _a;
  31. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  32. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  33. var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)();
  34. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  35. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  36. var _GM_unregisterMenuCommand = /* @__PURE__ */ (() => typeof GM_unregisterMenuCommand != "undefined" ? GM_unregisterMenuCommand : void 0)();
  37. var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  38. var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  39. var _monkeyWindow = /* @__PURE__ */ (() => window)();
  40. const _SCRIPT_NAME_ = "CSDN优化";
  41. const utils = Utils.noConflict();
  42. const domutils = DOMUtils.noConflict();
  43. const __pops = pops;
  44. const log = new utils.Log(
  45. _GM_info,
  46. _unsafeWindow.console || _monkeyWindow.console
  47. );
  48. const SCRIPT_NAME = ((_a = _GM_info == null ? void 0 : _GM_info.script) == null ? void 0 : _a.name) || _SCRIPT_NAME_;
  49. const DEBUG = false;
  50. log.config({
  51. debug: DEBUG,
  52. logMaxCount: 1e3,
  53. autoClearConsole: true,
  54. tag: true
  55. });
  56. Qmsg.config(
  57. Object.defineProperties(
  58. {
  59. html: true,
  60. autoClose: true,
  61. showClose: false
  62. },
  63. {
  64. position: {
  65. get() {
  66. return PopsPanel.getValue("qmsg-config-position", "bottom");
  67. }
  68. },
  69. maxNums: {
  70. get() {
  71. return PopsPanel.getValue("qmsg-config-maxnums", 5);
  72. }
  73. },
  74. showReverse: {
  75. get() {
  76. return PopsPanel.getValue("qmsg-config-showreverse", true);
  77. }
  78. },
  79. zIndex: {
  80. get() {
  81. let maxZIndex = Utils.getMaxZIndex();
  82. let popsMaxZIndex = pops.config.InstanceUtils.getPopsMaxZIndex(maxZIndex).zIndex;
  83. return Utils.getMaxValue(maxZIndex, popsMaxZIndex) + 100;
  84. }
  85. }
  86. }
  87. )
  88. );
  89. const GM_Menu = new utils.GM_Menu({
  90. GM_getValue: _GM_getValue,
  91. GM_setValue: _GM_setValue,
  92. GM_registerMenuCommand: _GM_registerMenuCommand,
  93. GM_unregisterMenuCommand: _GM_unregisterMenuCommand
  94. });
  95. const httpx = new utils.Httpx(_GM_xmlhttpRequest);
  96. httpx.interceptors.response.use(void 0, (data) => {
  97. log.error(["拦截器-请求错误", data]);
  98. if (data.type === "onabort") {
  99. Qmsg.warning("请求取消");
  100. } else if (data.type === "onerror") {
  101. Qmsg.error("请求异常");
  102. } else if (data.type === "ontimeout") {
  103. Qmsg.error("请求超时");
  104. } else {
  105. Qmsg.error("其它错误");
  106. }
  107. return data;
  108. });
  109. httpx.config({
  110. logDetails: DEBUG
  111. });
  112. ({
  113. Object: {
  114. defineProperty: _unsafeWindow.Object.defineProperty
  115. },
  116. Function: {
  117. apply: _unsafeWindow.Function.prototype.apply,
  118. call: _unsafeWindow.Function.prototype.call
  119. },
  120. Element: {
  121. appendChild: _unsafeWindow.Element.prototype.appendChild
  122. },
  123. setTimeout: _unsafeWindow.setTimeout
  124. });
  125. const addStyle = utils.addStyle.bind(utils);
  126. const $ = document.querySelector.bind(document);
  127. document.querySelectorAll.bind(document);
  128. const KEY = "GM_Panel";
  129. const ATTRIBUTE_INIT = "data-init";
  130. const ATTRIBUTE_KEY = "data-key";
  131. const ATTRIBUTE_DEFAULT_VALUE = "data-default-value";
  132. const ATTRIBUTE_INIT_MORE_VALUE = "data-init-more-value";
  133. const CSDNRouter = {
  134. /**
  135. * 判断是否是华为云联盟
  136. * + huaweicloud.csdn.net
  137. */
  138. isHuaWeiCloudBlog() {
  139. return Boolean(/huaweicloud.csdn.net/i.test(window.location.origin));
  140. },
  141. /**
  142. * 判断是否是博客
  143. * + blog.csdn.net
  144. */
  145. isBlog() {
  146. return Boolean(/blog.csdn.net/i.test(window.location.origin));
  147. },
  148. /**
  149. * 判断是否是文库
  150. * + wenku.csdn.net
  151. */
  152. isWenKu() {
  153. return Boolean(/wenku.csdn.net/i.test(window.location.origin));
  154. },
  155. /**
  156. * 判断是否是链接
  157. * + link.csdn.net
  158. */
  159. isLink() {
  160. return window.location.hostname === "link.csdn.net";
  161. },
  162. /**
  163. * 判断是否是搜索
  164. * + so.csdn.net
  165. */
  166. isSo() {
  167. return window.location.hostname === "so.csdn.net";
  168. },
  169. /**
  170. * 判断是否是C知道
  171. * + so.csdn.net/know
  172. * + /chat
  173. * + /so/ai
  174. */
  175. isSoCKnow() {
  176. return this.isSo() && (window.location.pathname.startsWith("/chat") || window.location.pathname.startsWith("/so/ai"));
  177. },
  178. /**
  179. * 判断是否是资源页面
  180. * + download.csdn.net
  181. */
  182. isDownload() {
  183. return window.location.hostname === "download.csdn.net";
  184. }
  185. };
  186. const UISlider = function(text, key, defaultValue, min, max, changeCallBack, getToolTipContent, description, step) {
  187. let result = {
  188. text,
  189. type: "slider",
  190. description,
  191. attributes: {},
  192. getValue() {
  193. return PopsPanel.getValue(key, defaultValue);
  194. },
  195. getToolTipContent(value) {
  196. if (typeof getToolTipContent === "function") {
  197. return getToolTipContent(value);
  198. } else {
  199. return `${value}`;
  200. }
  201. },
  202. callback(event, value) {
  203. if (typeof changeCallBack === "function") {
  204. if (changeCallBack(event, value)) {
  205. return;
  206. }
  207. }
  208. PopsPanel.setValue(key, value);
  209. },
  210. min,
  211. max,
  212. step
  213. };
  214. if (result.attributes) {
  215. result.attributes[ATTRIBUTE_KEY] = key;
  216. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = defaultValue;
  217. }
  218. return result;
  219. };
  220. const UISwitch = function(text, key, defaultValue, clickCallBack, description) {
  221. let result = {
  222. text,
  223. type: "switch",
  224. description,
  225. attributes: {},
  226. getValue() {
  227. return Boolean(PopsPanel.getValue(key, defaultValue));
  228. },
  229. callback(event, value) {
  230. log.success(`${value ? "开启" : "关闭"} ${text}`);
  231. if (typeof clickCallBack === "function") {
  232. if (clickCallBack(event, value)) {
  233. return;
  234. }
  235. }
  236. PopsPanel.setValue(key, Boolean(value));
  237. },
  238. afterAddToUListCallBack: void 0
  239. };
  240. if (result.attributes) {
  241. result.attributes[ATTRIBUTE_KEY] = key;
  242. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = Boolean(defaultValue);
  243. }
  244. return result;
  245. };
  246. const SettingUIBlog = {
  247. id: "panel-blog",
  248. title: "博客",
  249. isDefault() {
  250. return CSDNRouter.isBlog();
  251. },
  252. forms: [
  253. {
  254. text: "",
  255. type: "forms",
  256. forms: [
  257. {
  258. text: "全局屏蔽",
  259. type: "deepMenu",
  260. forms: [
  261. {
  262. text: "",
  263. type: "forms",
  264. forms: [
  265. UISwitch(
  266. "【屏蔽】登录弹窗",
  267. "csdn-blog-shieldLoginDialog",
  268. true
  269. ),
  270. UISwitch(
  271. "【屏蔽】左侧博客信息",
  272. "csdn-blog-shieldLeftBlogContainerAside",
  273. false
  274. ),
  275. UISwitch(
  276. "【屏蔽】右侧目录信息",
  277. "csdn-blog-shieldRightDirectoryInformation",
  278. false
  279. ),
  280. UISwitch(
  281. "【屏蔽】顶部工具栏",
  282. "csdn-blog-shieldTopToolbar",
  283. false
  284. ),
  285. UISwitch(
  286. "【屏蔽】底部的悬浮工具栏",
  287. "csdn-blog-shieldBottomFloatingToolbar",
  288. false
  289. )
  290. ]
  291. }
  292. ]
  293. },
  294. {
  295. text: "右侧悬浮工具栏",
  296. type: "deepMenu",
  297. forms: [
  298. {
  299. text: "功能",
  300. type: "forms",
  301. forms: [
  302. UISwitch(
  303. "启用",
  304. "csdn-blog-rightToolbarEnable",
  305. true,
  306. void 0,
  307. "创作中心,隐藏/显示侧栏,新手引导,客服、举报..."
  308. ),
  309. UISwitch(
  310. "【添加按钮】前往评论",
  311. "csdn-blog-addGotoRecommandButton",
  312. true,
  313. void 0,
  314. "在悬浮工具栏最后面添加"
  315. ),
  316. UISlider(
  317. "right偏移",
  318. "csdn-blog-rightToolbarRightOffset",
  319. 90,
  320. 0,
  321. document.documentElement.clientWidth,
  322. (event, value) => {
  323. let csdnSideToolbar = document.querySelector(
  324. ".csdn-side-toolbar"
  325. );
  326. domutils.css(csdnSideToolbar, {
  327. right: value + "px"
  328. });
  329. },
  330. (value) => {
  331. return `当前:${value}px,默认:90px`;
  332. }
  333. ),
  334. UISlider(
  335. "top偏移",
  336. "csdn-blog-rightToolbarTopOffset",
  337. 140,
  338. 0,
  339. document.documentElement.clientHeight,
  340. (event, value) => {
  341. let csdnSideToolbar = document.querySelector(
  342. ".csdn-side-toolbar"
  343. );
  344. domutils.css(csdnSideToolbar, {
  345. top: value + "px"
  346. });
  347. },
  348. (value) => {
  349. return `当前:${value}px,默认:90px`;
  350. }
  351. )
  352. ]
  353. },
  354. {
  355. text: "屏蔽",
  356. type: "forms",
  357. forms: [
  358. UISwitch(
  359. "【屏蔽】创作中心",
  360. "csdn-blog-rightToolbarCreativeCenter",
  361. false
  362. ),
  363. UISwitch(
  364. "【屏蔽】显示/隐藏侧栏",
  365. "csdn-blog-rightToolbarShowOrSidebar",
  366. false
  367. ),
  368. UISwitch(
  369. "【屏蔽】新手引导",
  370. "csdn-blog-rightToolbarBeginnerGuidance",
  371. false
  372. ),
  373. UISwitch(
  374. "【屏蔽】客服",
  375. "csdn-blog-rightToolbarCustomerService",
  376. false
  377. ),
  378. UISwitch("【屏蔽】举报", "csdn-blog-rightToolbarReport", false),
  379. UISwitch(
  380. "【屏蔽】返回顶部",
  381. "csdn-blog-rightToolbarBackToTop",
  382. false
  383. )
  384. ]
  385. }
  386. ]
  387. },
  388. {
  389. text: "内容",
  390. type: "deepMenu",
  391. forms: [
  392. {
  393. text: "功能",
  394. type: "forms",
  395. forms: [
  396. UISwitch(
  397. "点击代码块自动展开",
  398. "csdn-blog-clickPreCodeAutomatically",
  399. true,
  400. void 0,
  401. "当鼠标点击代码块区域时,将自动展开内容"
  402. ),
  403. UISwitch(
  404. "自动展开代码块",
  405. "csdn-blog-autoExpandCodeContent",
  406. true,
  407. void 0,
  408. "懒人操作,免手动点击展开"
  409. ),
  410. UISwitch(
  411. "自动展开内容",
  412. "csdn-blog-autoExpandContent",
  413. true,
  414. void 0,
  415. "懒人操作,免手动点击展开"
  416. ),
  417. UISwitch(
  418. "全文居中",
  419. "csdn-blog-articleCenter",
  420. true,
  421. function(event, enable) {
  422. if (enable) {
  423. alert(
  424. "为了更好的呈现效果,请开启功能:【屏蔽】左侧博客信息、【屏蔽】右侧目录信息"
  425. );
  426. }
  427. },
  428. "自动屏蔽左侧和右侧的信息,且将文章居中"
  429. ),
  430. UISwitch(
  431. "允许选择内容",
  432. "csdn-blog-allowSelectContent",
  433. true,
  434. void 0
  435. )
  436. ]
  437. },
  438. {
  439. text: "屏蔽",
  440. type: "forms",
  441. forms: [
  442. UISwitch(
  443. "【屏蔽】底部xx技能树",
  444. "csdn-blog-shieldBottomSkillTree",
  445. false
  446. ),
  447. UISwitch(
  448. "【屏蔽】选中文字悬浮栏",
  449. "csdn-blog-shieldArticleSearchTip",
  450. false,
  451. void 0,
  452. "选中文字弹出的,例如:搜索、评论、笔记"
  453. )
  454. ]
  455. }
  456. ]
  457. },
  458. {
  459. text: "评论区",
  460. type: "deepMenu",
  461. forms: [
  462. {
  463. text: "",
  464. type: "forms",
  465. forms: [
  466. UISwitch(
  467. "启用",
  468. "csdn-blog-blockComment",
  469. true,
  470. void 0,
  471. "关闭是屏蔽评论区"
  472. ),
  473. UISwitch("优化评论区的位置", "csdn-blog-restoreComments", true)
  474. ]
  475. }
  476. ]
  477. },
  478. {
  479. text: "底部文章",
  480. type: "deepMenu",
  481. forms: [
  482. {
  483. text: "",
  484. type: "forms",
  485. forms: [
  486. UISwitch(
  487. "启用",
  488. "csdn-blog-bottomRecommendArticleEnable",
  489. true,
  490. void 0,
  491. "关闭是屏蔽底部文章"
  492. ),
  493. UISwitch(
  494. "标识CSDN下载",
  495. "csdn-blog-identityCSDNDownload",
  496. true,
  497. void 0,
  498. "使用红框标识"
  499. ),
  500. UISwitch(
  501. "移除资源下载的文章",
  502. "csdn-blog-removeResourceDownloadArticle",
  503. false,
  504. void 0,
  505. "download.csdn.net<br>www.iteye.com<br>edu.csdn.net"
  506. )
  507. ]
  508. }
  509. ]
  510. },
  511. {
  512. text: "劫持/拦截",
  513. type: "deepMenu",
  514. forms: [
  515. {
  516. text: "",
  517. type: "forms",
  518. forms: [
  519. UISwitch(
  520. "拦截-复制的小尾巴",
  521. "csdn-blog-removeClipboardHijacking",
  522. true
  523. ),
  524. UISwitch(
  525. "劫持-禁止复制",
  526. "csdn-blog-unBlockCopy",
  527. true,
  528. void 0,
  529. "允许点击复制按钮进行复制"
  530. )
  531. ]
  532. }
  533. ]
  534. }
  535. ]
  536. }
  537. ]
  538. };
  539. const SettingUILink = {
  540. id: "panel-link",
  541. title: "链接",
  542. isDefault() {
  543. return CSDNRouter.isLink();
  544. },
  545. forms: [
  546. {
  547. text: "功能",
  548. type: "forms",
  549. forms: [
  550. UISwitch(
  551. "重定向链接",
  552. "csdn-link-jumpRedirect",
  553. true,
  554. void 0,
  555. "自动跳转至被拦截的Url链接"
  556. )
  557. ]
  558. }
  559. ]
  560. };
  561. const SettingUIHuaWeiCloud = {
  562. id: "panel-hua-wei-cloud",
  563. title: "华为云开发者联盟",
  564. isDefault() {
  565. return CSDNRouter.isHuaWeiCloudBlog();
  566. },
  567. forms: [
  568. {
  569. text: "功能",
  570. type: "forms",
  571. forms: [
  572. UISwitch("自动展开全文", "csdn-hua-wei-cloud-autoExpandContent", true)
  573. ]
  574. },
  575. {
  576. text: "屏蔽",
  577. type: "forms",
  578. forms: [
  579. UISwitch(
  580. "【屏蔽】云开发者任务挑战活动",
  581. "csdn-hua-wei-cloud-shieldCloudDeveloperTaskChallengeEvent",
  582. true
  583. ),
  584. UISwitch(
  585. "【屏蔽】左侧悬浮按钮",
  586. "csdn-hua-wei-cloud-shieldLeftFloatingButton",
  587. false,
  588. function(event, enable) {
  589. if (enable) {
  590. alert(
  591. "开启后将屏蔽【当前阅读量】、【点赞按钮】、【评论按钮】、【分享按钮】"
  592. );
  593. }
  594. }
  595. ),
  596. UISwitch(
  597. "【屏蔽】右侧栏",
  598. "csdn-hua-wei-cloud-blockRightColumn",
  599. false,
  600. function(event, enable) {
  601. if (enable) {
  602. alert(
  603. "开启后将屏蔽【相关产品】-【活动日历】-【运营活动】-【热门标签】"
  604. );
  605. }
  606. }
  607. ),
  608. UISwitch(
  609. "【屏蔽】底部推荐内容",
  610. "csdn-hua-wei-cloud-blockRecommendedContentAtTheBottom",
  611. false
  612. ),
  613. UISwitch(
  614. "【屏蔽】底部更多推荐",
  615. "csdn-hua-wei-cloud-shieldTheBottomForMoreRecommendations",
  616. false
  617. )
  618. ]
  619. }
  620. ]
  621. };
  622. const SettingUIWenKu = {
  623. id: "panel-wenku",
  624. title: "资源",
  625. isDefault() {
  626. return CSDNRouter.isLink();
  627. },
  628. forms: [
  629. {
  630. text: "屏蔽",
  631. type: "forms",
  632. forms: [
  633. UISwitch(
  634. "【屏蔽】资源推荐",
  635. "csdn-wenku-shieldResourceRecommend",
  636. false
  637. ),
  638. UISwitch(
  639. "【屏蔽】右侧用户信息",
  640. "csdn-wenku-shieldRightUserInfo",
  641. false
  642. ),
  643. UISwitch(
  644. "【屏蔽】右侧悬浮工具栏",
  645. "csdn-wenku-shieldRightToolBar",
  646. false
  647. )
  648. ]
  649. }
  650. ]
  651. };
  652. const SettingUISo = {
  653. id: "panel-so",
  654. title: "搜索",
  655. isDefault() {
  656. return CSDNRouter.isSo();
  657. },
  658. forms: [
  659. {
  660. text: "C知道-功能",
  661. type: "forms",
  662. forms: [UISwitch("去除水印", "csdn-so-cknow-removeMaskCover", true)]
  663. }
  664. ]
  665. };
  666. const MSettingUIBlog = {
  667. id: "m-panel-blog",
  668. title: "博客",
  669. isDefault() {
  670. return CSDNRouter.isBlog();
  671. },
  672. forms: [
  673. {
  674. type: "forms",
  675. text: "",
  676. forms: [
  677. {
  678. text: "功能",
  679. type: "deepMenu",
  680. forms: [
  681. {
  682. text: "",
  683. type: "forms",
  684. forms: [
  685. UISwitch(
  686. "【屏蔽】广告",
  687. "m-csdn-blog-removeAds",
  688. true,
  689. void 0,
  690. "包括:登录弹窗、打开APP、ios版本提示等"
  691. ),
  692. UISwitch(
  693. "允许复制",
  694. "m-csdn-blog-unBlockCopy",
  695. true,
  696. void 0,
  697. "允许点击复制按钮进行复制"
  698. )
  699. ]
  700. }
  701. ]
  702. }
  703. ]
  704. },
  705. {
  706. text: "",
  707. type: "forms",
  708. forms: [
  709. {
  710. type: "deepMenu",
  711. text: "顶部工具栏",
  712. forms: [
  713. {
  714. type: "forms",
  715. text: "",
  716. forms: [
  717. UISwitch(
  718. "启用",
  719. "m-csdn-blog-shieldTopToolbar",
  720. false,
  721. void 0,
  722. "关闭是屏蔽顶部工具栏"
  723. )
  724. ]
  725. }
  726. ]
  727. },
  728. {
  729. text: "内容",
  730. type: "deepMenu",
  731. forms: [
  732. {
  733. text: "",
  734. type: "forms",
  735. forms: [
  736. UISwitch(
  737. "允许选中文字",
  738. "m-csdn-blog-allowSelectText",
  739. true,
  740. void 0,
  741. "设置user-select: text;"
  742. ),
  743. UISwitch(
  744. "自动展开",
  745. "m-csdn-blog-autoExpandContent",
  746. true,
  747. void 0,
  748. "包括内容、代码块"
  749. ),
  750. UISwitch(
  751. "不限制代码块的最大高度",
  752. "m-csdn-blog-notLimitCodePreMaxHeight",
  753. false,
  754. void 0,
  755. "让代码块的高度直接被撑开"
  756. )
  757. ]
  758. }
  759. ]
  760. },
  761. {
  762. text: "评论",
  763. type: "deepMenu",
  764. forms: [
  765. {
  766. text: "",
  767. type: "forms",
  768. forms: [
  769. UISwitch(
  770. "启用",
  771. "m-csdn-blog-comment-enable",
  772. true,
  773. void 0,
  774. "关闭是屏蔽评论区"
  775. ),
  776. UISwitch(
  777. "不限制评论区的最大高度",
  778. "m-csdn-blog-notLimitCommentMaxHeight",
  779. true,
  780. void 0,
  781. "让评论区高度直接被撑开"
  782. )
  783. ]
  784. }
  785. ]
  786. },
  787. {
  788. text: "底部文章",
  789. type: "deepMenu",
  790. forms: [
  791. {
  792. text: "",
  793. type: "forms",
  794. forms: [
  795. UISwitch(
  796. "启用",
  797. "m-csdn-blog-bottomArticleEnable",
  798. true,
  799. void 0,
  800. "关闭是屏蔽底部文章"
  801. ),
  802. UISwitch(
  803. "移除资源下载",
  804. "m-csdn-blog-removeResourceArticle",
  805. false,
  806. void 0,
  807. "download.csdn.net<br>www.iteye.com<br>edu.csdn.net"
  808. ),
  809. UISwitch(
  810. "重构",
  811. "m-csdn-blog-refactoringRecommendation",
  812. true,
  813. void 0,
  814. "文章的样式统一"
  815. ),
  816. UISwitch(
  817. "新标签页打开",
  818. "m-csdn-blog-openNewTab",
  819. true,
  820. void 0,
  821. "新标签页打开文章"
  822. )
  823. ]
  824. }
  825. ]
  826. },
  827. {
  828. type: "deepMenu",
  829. text: "底部工具栏",
  830. forms: [
  831. {
  832. type: "forms",
  833. text: "",
  834. forms: [
  835. UISwitch(
  836. "启用",
  837. "m-csdn-blog-bottom-toolbar-enable",
  838. false,
  839. void 0,
  840. "关闭是屏蔽底部工具栏"
  841. ),
  842. UISwitch(
  843. "常驻底部",
  844. "m-csdn-blog-bottom-toolbar-always-bottom",
  845. false,
  846. void 0,
  847. "开启后底部工具栏不随下滑滚动而隐藏"
  848. ),
  849. UISwitch(
  850. "优化收藏按钮",
  851. "m-csdn-blog-bottom-toolbar-optimizationCollectButton",
  852. false,
  853. void 0,
  854. "可以自行选择收藏夹"
  855. )
  856. ]
  857. }
  858. ]
  859. }
  860. ]
  861. }
  862. ]
  863. };
  864. const MSettingUILink = {
  865. id: "m-panel-link",
  866. title: "链接",
  867. isDefault() {
  868. return CSDNRouter.isLink();
  869. },
  870. forms: [
  871. {
  872. text: "功能",
  873. type: "forms",
  874. forms: [
  875. UISwitch(
  876. "重定向链接",
  877. "m-csdn-link-jumpRedirect",
  878. true,
  879. void 0,
  880. "自动跳转至被拦截的Url链接"
  881. )
  882. ]
  883. }
  884. ]
  885. };
  886. const MSettingUISo = {
  887. id: "panel-so",
  888. title: "搜索",
  889. isDefault() {
  890. return CSDNRouter.isSo();
  891. },
  892. forms: [
  893. {
  894. text: "C知道-功能",
  895. type: "forms",
  896. forms: [UISwitch("去除水印", "m-csdn-so-cknow-removeMaskCover", true)]
  897. }
  898. ]
  899. };
  900. const MSettingUIWenKu = {
  901. id: "m-panel-wenku",
  902. title: "文库",
  903. isDefault() {
  904. return CSDNRouter.isWenKu();
  905. },
  906. forms: [
  907. {
  908. text: "屏蔽",
  909. type: "forms",
  910. forms: [
  911. UISwitch(
  912. "【屏蔽】底部工具栏",
  913. "m-csdn-wenku-shieldBottomToolbar",
  914. false
  915. )
  916. ]
  917. }
  918. ]
  919. };
  920. const MSettingUIHuaWeiCloud = {
  921. id: "m-panel-hua-wei-cloud",
  922. title: "华为云开发者联盟",
  923. isDefault() {
  924. return CSDNRouter.isHuaWeiCloudBlog();
  925. },
  926. forms: [
  927. {
  928. text: "功能",
  929. type: "forms",
  930. forms: [
  931. UISwitch(
  932. "自动展开全文",
  933. "m-csdn-hua-wei-cloud-autoExpandContent",
  934. true
  935. )
  936. ]
  937. },
  938. {
  939. text: "屏蔽",
  940. type: "forms",
  941. forms: [
  942. UISwitch(
  943. "【屏蔽】底部加入社区",
  944. "m-csdn-hua-wei-cloud-blockBottomJoinTheCommunity",
  945. true
  946. )
  947. ]
  948. }
  949. ]
  950. };
  951. const MSettingUIDownload = {
  952. id: "m-panel-download",
  953. title: "资源",
  954. isDefault() {
  955. return CSDNRouter.isDownload();
  956. },
  957. forms: [
  958. {
  959. text: "功能",
  960. type: "forms",
  961. forms: [
  962. UISwitch(
  963. "自动展开资源介绍",
  964. "m-csdn-download-automaticallyExpandResourceIntroduction",
  965. true,
  966. void 0,
  967. "屏蔽资源介绍【展开全部】按钮并展开资源介绍"
  968. )
  969. ]
  970. },
  971. {
  972. text: "屏蔽",
  973. type: "forms",
  974. forms: [
  975. UISwitch(
  976. "【屏蔽】广告",
  977. "m-csdn-download-removeAds",
  978. true,
  979. void 0,
  980. "包括:登录弹窗、会员降价等"
  981. )
  982. ]
  983. }
  984. ]
  985. };
  986. const UISelect = function(text, key, defaultValue, data, callback, description) {
  987. let selectData = [];
  988. if (typeof data === "function") {
  989. selectData = data();
  990. } else {
  991. selectData = data;
  992. }
  993. let result = {
  994. text,
  995. type: "select",
  996. description,
  997. attributes: {},
  998. getValue() {
  999. return PopsPanel.getValue(key, defaultValue);
  1000. },
  1001. callback(event, isSelectedValue, isSelectedText) {
  1002. PopsPanel.setValue(key, isSelectedValue);
  1003. if (typeof callback === "function") {
  1004. callback(event, isSelectedValue, isSelectedText);
  1005. }
  1006. },
  1007. data: selectData
  1008. };
  1009. if (result.attributes) {
  1010. result.attributes[ATTRIBUTE_KEY] = key;
  1011. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = defaultValue;
  1012. }
  1013. return result;
  1014. };
  1015. const SettingUICommon = {
  1016. id: "component-common",
  1017. title: "通用",
  1018. forms: [
  1019. {
  1020. text: "Toast配置",
  1021. type: "forms",
  1022. forms: [
  1023. UISelect(
  1024. "Toast位置",
  1025. "qmsg-config-position",
  1026. "bottom",
  1027. [
  1028. {
  1029. value: "topleft",
  1030. text: "左上角"
  1031. },
  1032. {
  1033. value: "top",
  1034. text: "顶部"
  1035. },
  1036. {
  1037. value: "topright",
  1038. text: "右上角"
  1039. },
  1040. {
  1041. value: "left",
  1042. text: "左边"
  1043. },
  1044. {
  1045. value: "center",
  1046. text: "中间"
  1047. },
  1048. {
  1049. value: "right",
  1050. text: "右边"
  1051. },
  1052. {
  1053. value: "bottomleft",
  1054. text: "左下角"
  1055. },
  1056. {
  1057. value: "bottom",
  1058. text: "底部"
  1059. },
  1060. {
  1061. value: "bottomright",
  1062. text: "右下角"
  1063. }
  1064. ],
  1065. (event, isSelectValue, isSelectText) => {
  1066. log.info("设置当前Qmsg弹出位置" + isSelectText);
  1067. },
  1068. "Toast显示在页面九宫格的位置"
  1069. ),
  1070. UISelect(
  1071. "最多显示的数量",
  1072. "qmsg-config-maxnums",
  1073. 3,
  1074. [
  1075. {
  1076. value: 1,
  1077. text: "1"
  1078. },
  1079. {
  1080. value: 2,
  1081. text: "2"
  1082. },
  1083. {
  1084. value: 3,
  1085. text: "3"
  1086. },
  1087. {
  1088. value: 4,
  1089. text: "4"
  1090. },
  1091. {
  1092. value: 5,
  1093. text: "5"
  1094. }
  1095. ],
  1096. void 0,
  1097. "限制Toast显示的数量"
  1098. ),
  1099. UISwitch(
  1100. "逆序弹出",
  1101. "qmsg-config-showreverse",
  1102. false,
  1103. void 0,
  1104. "修改Toast弹出的顺序"
  1105. )
  1106. ]
  1107. }
  1108. // {
  1109. // text: "Cookie配置",
  1110. // type: "forms",
  1111. // forms: [
  1112. // UISwitch(
  1113. // "启用",
  1114. // "httpx-use-cookie-enable",
  1115. // false,
  1116. // void 0,
  1117. // "启用后,将根据下面的配置进行添加cookie"
  1118. // ),
  1119. // UISwitch(
  1120. // "使用document.cookie",
  1121. // "httpx-use-document-cookie",
  1122. // false,
  1123. // void 0,
  1124. // "自动根据请求的域名来设置对应的cookie"
  1125. // ),
  1126. // UITextArea(
  1127. // "tieba.baidu.com",
  1128. // "httpx-cookie-tieba.baidu.com",
  1129. // "",
  1130. // void 0,
  1131. // void 0,
  1132. // "Cookie格式:xxx=xxxx;xxx=xxxx"
  1133. // ),
  1134. // ],
  1135. // },
  1136. ]
  1137. };
  1138. const MSettingUICommon = {
  1139. id: "component-common",
  1140. title: "通用",
  1141. forms: [
  1142. {
  1143. text: "Toast配置",
  1144. type: "forms",
  1145. forms: [
  1146. UISelect(
  1147. "Toast位置",
  1148. "qmsg-config-position",
  1149. "bottom",
  1150. [
  1151. {
  1152. value: "topleft",
  1153. text: "左上角"
  1154. },
  1155. {
  1156. value: "top",
  1157. text: "顶部"
  1158. },
  1159. {
  1160. value: "topright",
  1161. text: "右上角"
  1162. },
  1163. {
  1164. value: "left",
  1165. text: "左边"
  1166. },
  1167. {
  1168. value: "center",
  1169. text: "中间"
  1170. },
  1171. {
  1172. value: "right",
  1173. text: "右边"
  1174. },
  1175. {
  1176. value: "bottomleft",
  1177. text: "左下角"
  1178. },
  1179. {
  1180. value: "bottom",
  1181. text: "底部"
  1182. },
  1183. {
  1184. value: "bottomright",
  1185. text: "右下角"
  1186. }
  1187. ],
  1188. (event, isSelectValue, isSelectText) => {
  1189. log.info("设置当前Qmsg弹出位置" + isSelectText);
  1190. },
  1191. "Toast显示在页面九宫格的位置"
  1192. ),
  1193. UISelect(
  1194. "最多显示的数量",
  1195. "qmsg-config-maxnums",
  1196. 3,
  1197. [
  1198. {
  1199. value: 1,
  1200. text: "1"
  1201. },
  1202. {
  1203. value: 2,
  1204. text: "2"
  1205. },
  1206. {
  1207. value: 3,
  1208. text: "3"
  1209. },
  1210. {
  1211. value: 4,
  1212. text: "4"
  1213. },
  1214. {
  1215. value: 5,
  1216. text: "5"
  1217. }
  1218. ],
  1219. void 0,
  1220. "限制Toast显示的数量"
  1221. ),
  1222. UISwitch(
  1223. "逆序弹出",
  1224. "qmsg-config-showreverse",
  1225. false,
  1226. void 0,
  1227. "修改Toast弹出的顺序"
  1228. )
  1229. ]
  1230. }
  1231. // {
  1232. // text: "Cookie配置",
  1233. // type: "forms",
  1234. // forms: [
  1235. // UISwitch(
  1236. // "启用",
  1237. // "httpx-use-cookie-enable",
  1238. // false,
  1239. // void 0,
  1240. // "启用后,将根据下面的配置进行添加cookie"
  1241. // ),
  1242. // UISwitch(
  1243. // "使用document.cookie",
  1244. // "httpx-use-document-cookie",
  1245. // false,
  1246. // void 0,
  1247. // "自动根据请求的域名来设置对应的cookie"
  1248. // ),
  1249. // UITextArea(
  1250. // "tieba.baidu.com",
  1251. // "httpx-cookie-tieba.baidu.com",
  1252. // "",
  1253. // void 0,
  1254. // void 0,
  1255. // "Cookie格式:xxx=xxxx;xxx=xxxx"
  1256. // ),
  1257. // ],
  1258. // },
  1259. ]
  1260. };
  1261. const PanelUISize = {
  1262. /**
  1263. * 一般设置界面的尺寸
  1264. */
  1265. setting: {
  1266. width: window.innerWidth < 550 ? "88vw" : "550px",
  1267. height: window.innerHeight < 450 ? "70vh" : "450px"
  1268. },
  1269. /**
  1270. * 功能丰富,aside铺满了的设置界面,要稍微大一点
  1271. */
  1272. settingBig: {
  1273. width: window.innerWidth < 800 ? "92vw" : "800px",
  1274. height: window.innerHeight < 600 ? "80vh" : "600px"
  1275. },
  1276. /**
  1277. * 信息界面,一般用于提示信息之类
  1278. */
  1279. info: {
  1280. width: window.innerWidth < 350 ? "350px" : "350px",
  1281. height: window.innerHeight < 250 ? "250px" : "250px"
  1282. }
  1283. };
  1284. const PopsPanel = {
  1285. /** 数据 */
  1286. $data: {
  1287. __data: null,
  1288. __oneSuccessExecMenu: null,
  1289. __onceExec: null,
  1290. __listenData: null,
  1291. /**
  1292. * 菜单项的默认值
  1293. */
  1294. get data() {
  1295. if (PopsPanel.$data.__data == null) {
  1296. PopsPanel.$data.__data = new utils.Dictionary();
  1297. }
  1298. return PopsPanel.$data.__data;
  1299. },
  1300. /**
  1301. * 成功只执行了一次的项
  1302. */
  1303. get oneSuccessExecMenu() {
  1304. if (PopsPanel.$data.__oneSuccessExecMenu == null) {
  1305. PopsPanel.$data.__oneSuccessExecMenu = new utils.Dictionary();
  1306. }
  1307. return PopsPanel.$data.__oneSuccessExecMenu;
  1308. },
  1309. /**
  1310. * 成功只执行了一次的项
  1311. */
  1312. get onceExec() {
  1313. if (PopsPanel.$data.__onceExec == null) {
  1314. PopsPanel.$data.__onceExec = new utils.Dictionary();
  1315. }
  1316. return PopsPanel.$data.__onceExec;
  1317. },
  1318. /** 脚本名,一般用在设置的标题上 */
  1319. get scriptName() {
  1320. return SCRIPT_NAME;
  1321. },
  1322. /** 菜单项的总值在本地数据配置的键名 */
  1323. key: KEY,
  1324. /** 菜单项在attributes上配置的菜单键 */
  1325. attributeKeyName: ATTRIBUTE_KEY,
  1326. /** 菜单项在attributes上配置的菜单默认值 */
  1327. attributeDefaultValueName: ATTRIBUTE_DEFAULT_VALUE
  1328. },
  1329. /** 监听器 */
  1330. $listener: {
  1331. /**
  1332. * 值改变的监听器
  1333. */
  1334. get listenData() {
  1335. if (PopsPanel.$data.__listenData == null) {
  1336. PopsPanel.$data.__listenData = new utils.Dictionary();
  1337. }
  1338. return PopsPanel.$data.__listenData;
  1339. }
  1340. },
  1341. init() {
  1342. this.initPanelDefaultValue();
  1343. this.initExtensionsMenu();
  1344. },
  1345. initExtensionsMenu() {
  1346. if (_unsafeWindow.top !== _unsafeWindow.self) {
  1347. return;
  1348. }
  1349. GM_Menu.add([
  1350. {
  1351. key: "show_pops_panel_setting",
  1352. text: "⚙ PC端设置",
  1353. autoReload: false,
  1354. isStoreValue: false,
  1355. showText(text) {
  1356. return text;
  1357. },
  1358. callback: () => {
  1359. this.showPanel();
  1360. }
  1361. },
  1362. {
  1363. key: "m_show_pops_panel_setting",
  1364. text: "⚙ 移动端端设置",
  1365. autoReload: false,
  1366. isStoreValue: false,
  1367. showText(text) {
  1368. return text;
  1369. },
  1370. callback: () => {
  1371. this.showMPanel();
  1372. }
  1373. },
  1374. {
  1375. key: "gotoCSDNCKnow",
  1376. text: "⚙ 前往C知道",
  1377. isStoreValue: false,
  1378. autoReload: false,
  1379. showText(text) {
  1380. return text;
  1381. },
  1382. callback() {
  1383. window.open("https://so.csdn.net/chat", "_blank");
  1384. }
  1385. }
  1386. ]);
  1387. },
  1388. /** 初始化菜单项的默认值保存到本地数据中 */
  1389. initPanelDefaultValue() {
  1390. let that = this;
  1391. function initDefaultValue(config) {
  1392. if (!config.attributes) {
  1393. return;
  1394. }
  1395. let needInitConfig = {};
  1396. let key = config.attributes[ATTRIBUTE_KEY];
  1397. if (key != null) {
  1398. needInitConfig[key] = config.attributes[ATTRIBUTE_DEFAULT_VALUE];
  1399. }
  1400. let __attr_init__ = config.attributes[ATTRIBUTE_INIT];
  1401. if (typeof __attr_init__ === "function") {
  1402. let __attr_result__ = __attr_init__();
  1403. if (typeof __attr_result__ === "boolean" && !__attr_result__) {
  1404. return;
  1405. }
  1406. }
  1407. let initMoreValue = config.attributes[ATTRIBUTE_INIT_MORE_VALUE];
  1408. if (initMoreValue && typeof initMoreValue === "object") {
  1409. Object.assign(needInitConfig, initMoreValue);
  1410. }
  1411. let needInitConfigList = Object.keys(needInitConfig);
  1412. if (!needInitConfigList.length) {
  1413. log.warn(["请先配置键", config]);
  1414. return;
  1415. }
  1416. needInitConfigList.forEach((__key) => {
  1417. let __defaultValue = needInitConfig[__key];
  1418. if (that.$data.data.has(__key)) {
  1419. log.warn("请检查该key(已存在): " + __key);
  1420. }
  1421. that.$data.data.set(__key, __defaultValue);
  1422. });
  1423. }
  1424. function loopInitDefaultValue(configList) {
  1425. for (let index = 0; index < configList.length; index++) {
  1426. let configItem = configList[index];
  1427. initDefaultValue(configItem);
  1428. let childForms = configItem.forms;
  1429. if (childForms && Array.isArray(childForms)) {
  1430. loopInitDefaultValue(childForms);
  1431. }
  1432. }
  1433. }
  1434. let contentConfigList = this.getPanelContentConfig().concat(
  1435. this.getMPanelContentConfig()
  1436. );
  1437. for (let index = 0; index < contentConfigList.length; index++) {
  1438. let leftContentConfigItem = contentConfigList[index];
  1439. if (!leftContentConfigItem.forms) {
  1440. continue;
  1441. }
  1442. let rightContentConfigList = leftContentConfigItem.forms;
  1443. if (rightContentConfigList && Array.isArray(rightContentConfigList)) {
  1444. loopInitDefaultValue(rightContentConfigList);
  1445. }
  1446. }
  1447. },
  1448. /**
  1449. * 设置值
  1450. * @param key 键
  1451. * @param value 值
  1452. */
  1453. setValue(key, value) {
  1454. let locaData = _GM_getValue(KEY, {});
  1455. let oldValue = locaData[key];
  1456. locaData[key] = value;
  1457. _GM_setValue(KEY, locaData);
  1458. if (this.$listener.listenData.has(key)) {
  1459. this.$listener.listenData.get(key).callback(key, oldValue, value);
  1460. }
  1461. },
  1462. /**
  1463. * 获取值
  1464. * @param key 键
  1465. * @param defaultValue 默认值
  1466. */
  1467. getValue(key, defaultValue) {
  1468. let locaData = _GM_getValue(KEY, {});
  1469. let localValue = locaData[key];
  1470. if (localValue == null) {
  1471. if (this.$data.data.has(key)) {
  1472. return this.$data.data.get(key);
  1473. }
  1474. return defaultValue;
  1475. }
  1476. return localValue;
  1477. },
  1478. /**
  1479. * 删除值
  1480. * @param key 键
  1481. */
  1482. deleteValue(key) {
  1483. let locaData = _GM_getValue(KEY, {});
  1484. let oldValue = locaData[key];
  1485. Reflect.deleteProperty(locaData, key);
  1486. _GM_setValue(KEY, locaData);
  1487. if (this.$listener.listenData.has(key)) {
  1488. this.$listener.listenData.get(key).callback(key, oldValue, void 0);
  1489. }
  1490. },
  1491. /**
  1492. * 监听调用setValue、deleteValue
  1493. * @param key 需要监听的键
  1494. * @param callback
  1495. */
  1496. addValueChangeListener(key, callback, option) {
  1497. let listenerId = Math.random();
  1498. this.$listener.listenData.set(key, {
  1499. id: listenerId,
  1500. key,
  1501. callback
  1502. });
  1503. if (option) {
  1504. if (option.immediate) {
  1505. callback(key, this.getValue(key), this.getValue(key));
  1506. }
  1507. }
  1508. return listenerId;
  1509. },
  1510. /**
  1511. * 移除监听
  1512. * @param listenerId 监听的id
  1513. */
  1514. removeValueChangeListener(listenerId) {
  1515. let deleteKey = null;
  1516. for (const [key, value] of this.$listener.listenData.entries()) {
  1517. if (value.id === listenerId) {
  1518. deleteKey = key;
  1519. break;
  1520. }
  1521. }
  1522. if (typeof deleteKey === "string") {
  1523. this.$listener.listenData.delete(deleteKey);
  1524. } else {
  1525. console.warn("没有找到对应的监听器");
  1526. }
  1527. },
  1528. /**
  1529. * 主动触发菜单值改变的回调
  1530. * @param key 菜单键
  1531. * @param newValue 想要触发的新值,默认使用当前值
  1532. * @param oldValue 想要触发的旧值,默认使用当前值
  1533. */
  1534. triggerMenuValueChange(key, newValue, oldValue) {
  1535. if (this.$listener.listenData.has(key)) {
  1536. let listenData = this.$listener.listenData.get(key);
  1537. if (typeof listenData.callback === "function") {
  1538. let value = this.getValue(key);
  1539. let __newValue = value;
  1540. let __oldValue = value;
  1541. if (typeof newValue !== "undefined" && arguments.length > 1) {
  1542. __newValue = newValue;
  1543. }
  1544. if (typeof oldValue !== "undefined" && arguments.length > 2) {
  1545. __oldValue = oldValue;
  1546. }
  1547. listenData.callback(key, __oldValue, __newValue);
  1548. }
  1549. }
  1550. },
  1551. /**
  1552. * 判断该键是否存在
  1553. * @param key 键
  1554. */
  1555. hasKey(key) {
  1556. let locaData = _GM_getValue(KEY, {});
  1557. return key in locaData;
  1558. },
  1559. /**
  1560. * 自动判断菜单是否启用,然后执行回调
  1561. * @param key
  1562. * @param callback 回调
  1563. * @param [isReverse=false] 逆反判断菜单启用
  1564. */
  1565. execMenu(key, callback, isReverse = false) {
  1566. if (!(typeof key === "string" || typeof key === "object" && Array.isArray(key))) {
  1567. throw new TypeError("key 必须是字符串或者字符串数组");
  1568. }
  1569. let runKeyList = [];
  1570. if (typeof key === "object" && Array.isArray(key)) {
  1571. runKeyList = [...key];
  1572. } else {
  1573. runKeyList.push(key);
  1574. }
  1575. let value = void 0;
  1576. for (let index = 0; index < runKeyList.length; index++) {
  1577. const runKey = runKeyList[index];
  1578. if (!this.$data.data.has(runKey)) {
  1579. log.warn(`${key} 键不存在`);
  1580. return;
  1581. }
  1582. let runValue = PopsPanel.getValue(runKey);
  1583. if (isReverse) {
  1584. runValue = !runValue;
  1585. }
  1586. if (!runValue) {
  1587. break;
  1588. }
  1589. value = runValue;
  1590. }
  1591. if (value) {
  1592. callback(value);
  1593. }
  1594. },
  1595. /**
  1596. * 自动判断菜单是否启用,然后执行回调,只会执行一次
  1597. * @param key
  1598. * @param callback 回调
  1599. * @param getValueFn 自定义处理获取当前值,值true是启用并执行回调,值false是不执行回调
  1600. * @param handleValueChangeFn 自定义处理值改变时的回调,值true是启用并执行回调,值false是不执行回调
  1601. */
  1602. execMenuOnce(key, callback, getValueFn, handleValueChangeFn) {
  1603. if (typeof key !== "string") {
  1604. throw new TypeError("key 必须是字符串");
  1605. }
  1606. if (!this.$data.data.has(key)) {
  1607. log.warn(`${key} 键不存在`);
  1608. return;
  1609. }
  1610. if (this.$data.oneSuccessExecMenu.has(key)) {
  1611. return;
  1612. }
  1613. this.$data.oneSuccessExecMenu.set(key, 1);
  1614. let __getValue = () => {
  1615. let localValue = PopsPanel.getValue(key);
  1616. return typeof getValueFn === "function" ? getValueFn(key, localValue) : localValue;
  1617. };
  1618. let resultStyleList = [];
  1619. let dynamicPushStyleNode = ($style) => {
  1620. let __value = __getValue();
  1621. let dynamicResultList = [];
  1622. if ($style instanceof HTMLStyleElement) {
  1623. dynamicResultList = [$style];
  1624. } else if (Array.isArray($style)) {
  1625. dynamicResultList = [
  1626. ...$style.filter(
  1627. (item) => item != null && item instanceof HTMLStyleElement
  1628. )
  1629. ];
  1630. }
  1631. if (__value) {
  1632. resultStyleList = resultStyleList.concat(dynamicResultList);
  1633. } else {
  1634. for (let index = 0; index < dynamicResultList.length; index++) {
  1635. let $css = dynamicResultList[index];
  1636. $css.remove();
  1637. dynamicResultList.splice(index, 1);
  1638. index--;
  1639. }
  1640. }
  1641. };
  1642. let changeCallBack = (currentValue) => {
  1643. let resultList = [];
  1644. if (currentValue) {
  1645. let result = callback(currentValue, dynamicPushStyleNode);
  1646. if (result instanceof HTMLStyleElement) {
  1647. resultList = [result];
  1648. } else if (Array.isArray(result)) {
  1649. resultList = [
  1650. ...result.filter(
  1651. (item) => item != null && item instanceof HTMLStyleElement
  1652. )
  1653. ];
  1654. }
  1655. }
  1656. for (let index = 0; index < resultStyleList.length; index++) {
  1657. let $css = resultStyleList[index];
  1658. $css.remove();
  1659. resultStyleList.splice(index, 1);
  1660. index--;
  1661. }
  1662. resultStyleList = [...resultList];
  1663. };
  1664. this.addValueChangeListener(
  1665. key,
  1666. (__key, oldValue, newValue) => {
  1667. let __newValue = newValue;
  1668. if (typeof handleValueChangeFn === "function") {
  1669. __newValue = handleValueChangeFn(__key, newValue, oldValue);
  1670. }
  1671. changeCallBack(__newValue);
  1672. }
  1673. );
  1674. let value = __getValue();
  1675. if (value) {
  1676. changeCallBack(value);
  1677. }
  1678. },
  1679. /**
  1680. * 父子菜单联动,自动判断菜单是否启用,然后执行回调,只会执行一次
  1681. * @param key 菜单键
  1682. * @param childKey 子菜单键
  1683. * @param callback 回调
  1684. * @param replaceValueFn 用于修改mainValue,返回undefined则不做处理
  1685. */
  1686. execInheritMenuOnce(key, childKey, callback, replaceValueFn) {
  1687. let that = this;
  1688. const handleInheritValue = (key2, childKey2) => {
  1689. let mainValue = that.getValue(key2);
  1690. let childValue = that.getValue(childKey2);
  1691. if (typeof replaceValueFn === "function") {
  1692. let changedMainValue = replaceValueFn(mainValue, childValue);
  1693. if (changedMainValue !== void 0) {
  1694. return changedMainValue;
  1695. }
  1696. }
  1697. return mainValue;
  1698. };
  1699. this.execMenuOnce(
  1700. key,
  1701. callback,
  1702. () => {
  1703. return handleInheritValue(key, childKey);
  1704. },
  1705. () => {
  1706. return handleInheritValue(key, childKey);
  1707. }
  1708. );
  1709. this.execMenuOnce(
  1710. childKey,
  1711. () => {
  1712. },
  1713. () => false,
  1714. () => {
  1715. this.triggerMenuValueChange(key);
  1716. return false;
  1717. }
  1718. );
  1719. },
  1720. /**
  1721. * 根据key执行一次
  1722. * @param key
  1723. */
  1724. onceExec(key, callback) {
  1725. if (typeof key !== "string") {
  1726. throw new TypeError("key 必须是字符串");
  1727. }
  1728. if (this.$data.onceExec.has(key)) {
  1729. return;
  1730. }
  1731. callback();
  1732. this.$data.onceExec.set(key, 1);
  1733. },
  1734. /**
  1735. * 显示设置面板
  1736. */
  1737. showPanel() {
  1738. __pops.panel({
  1739. title: {
  1740. text: `${SCRIPT_NAME}-PC端设置`,
  1741. position: "center",
  1742. html: false,
  1743. style: ""
  1744. },
  1745. content: this.getPanelContentConfig(),
  1746. mask: {
  1747. enable: true,
  1748. clickEvent: {
  1749. toClose: true,
  1750. toHide: false
  1751. }
  1752. },
  1753. width: PanelUISize.setting.width,
  1754. height: PanelUISize.setting.height,
  1755. drag: true,
  1756. only: true
  1757. });
  1758. },
  1759. /**
  1760. * 显示设置面板
  1761. */
  1762. showMPanel() {
  1763. __pops.panel({
  1764. title: {
  1765. text: `${SCRIPT_NAME}-移动端设置`,
  1766. position: "center",
  1767. html: false,
  1768. style: ""
  1769. },
  1770. content: this.getMPanelContentConfig(),
  1771. mask: {
  1772. enable: true,
  1773. clickEvent: {
  1774. toClose: true,
  1775. toHide: false
  1776. }
  1777. },
  1778. width: PanelUISize.setting.width,
  1779. height: PanelUISize.setting.height,
  1780. drag: true,
  1781. only: true
  1782. });
  1783. },
  1784. /**
  1785. * 判断是否是移动端
  1786. */
  1787. isMobile() {
  1788. return window.innerWidth < 550;
  1789. },
  1790. /**
  1791. * 获取设置面板的宽度
  1792. */
  1793. getWidth() {
  1794. if (window.innerWidth < 550) {
  1795. return "92vw";
  1796. } else {
  1797. return "550px";
  1798. }
  1799. },
  1800. /**
  1801. * 获取设置面板的高度
  1802. */
  1803. getHeight() {
  1804. if (window.innerHeight > 450) {
  1805. return "80vh";
  1806. } else {
  1807. return "450px";
  1808. }
  1809. },
  1810. /**
  1811. * 获取配置内容
  1812. */
  1813. getPanelContentConfig() {
  1814. let configList = [
  1815. SettingUICommon,
  1816. SettingUIBlog,
  1817. SettingUILink,
  1818. SettingUIHuaWeiCloud,
  1819. SettingUIWenKu,
  1820. SettingUISo
  1821. ];
  1822. return configList;
  1823. },
  1824. /**
  1825. * 获取配置内容
  1826. */
  1827. getMPanelContentConfig() {
  1828. let configList = [
  1829. MSettingUICommon,
  1830. MSettingUIBlog,
  1831. MSettingUILink,
  1832. MSettingUIHuaWeiCloud,
  1833. MSettingUIWenKu,
  1834. MSettingUISo,
  1835. MSettingUIDownload
  1836. ];
  1837. return configList;
  1838. }
  1839. };
  1840. const ShieldCSS$4 = "/* 底部免费抽xxx奖品广告 */\r\ndiv.siderbar-box,\r\n/* 华为开发者联盟加入社区 */\r\ndiv.user-desc.user-desc-fix {\r\n display: none !important;\r\n}\r\n";
  1841. const CommonUtil = {
  1842. /**
  1843. * 移除元素(未出现也可以等待出现)
  1844. * @param selector 元素选择器
  1845. */
  1846. waitRemove(...args) {
  1847. args.forEach((selector) => {
  1848. utils.waitNodeList(selector).then((nodeList) => {
  1849. nodeList.forEach((item) => item.remove());
  1850. });
  1851. });
  1852. },
  1853. /**
  1854. * 添加屏蔽CSS
  1855. * @param args
  1856. * @example
  1857. * addBlockCSS("")
  1858. * addBlockCSS("","")
  1859. * addBlockCSS(["",""])
  1860. */
  1861. addBlockCSS(...args) {
  1862. let selectorList = [];
  1863. if (args.length === 0) {
  1864. return;
  1865. }
  1866. if (args.length === 1 && typeof args[0] === "string" && args[0].trim() === "") {
  1867. return;
  1868. }
  1869. args.forEach((selector) => {
  1870. if (Array.isArray(selector)) {
  1871. selectorList = selectorList.concat(selector);
  1872. } else {
  1873. selectorList.push(selector);
  1874. }
  1875. });
  1876. return addStyle(`${selectorList.join(",\n")}{display: none !important;}`);
  1877. }
  1878. };
  1879. const CSDNHuaWeiCloud = {
  1880. init() {
  1881. addStyle(ShieldCSS$4);
  1882. PopsPanel.execMenuOnce(
  1883. "csdn-hua-wei-cloud-shieldCloudDeveloperTaskChallengeEvent",
  1884. () => {
  1885. return this.shieldCloudDeveloperTaskChallengeEvent();
  1886. }
  1887. );
  1888. PopsPanel.execMenuOnce("csdn-hua-wei-cloud-autoExpandContent", () => {
  1889. return this.autoExpandContent();
  1890. });
  1891. PopsPanel.execMenuOnce(
  1892. "csdn-hua-wei-cloud-shieldLeftFloatingButton",
  1893. () => {
  1894. return this.shieldLeftFloatingButton();
  1895. }
  1896. );
  1897. PopsPanel.execMenuOnce("csdn-hua-wei-cloud-blockRightColumn", () => {
  1898. return this.blockRightColumn();
  1899. });
  1900. PopsPanel.execMenuOnce(
  1901. "csdn-hua-wei-cloud-blockRecommendedContentAtTheBottom",
  1902. () => {
  1903. return this.blockRecommendedContentAtTheBottom();
  1904. }
  1905. );
  1906. PopsPanel.execMenuOnce(
  1907. "csdn-hua-wei-cloud-shieldTheBottomForMoreRecommendations",
  1908. () => {
  1909. return this.shieldTheBottomForMoreRecommendations();
  1910. }
  1911. );
  1912. },
  1913. /**
  1914. * 自动展开内容
  1915. */
  1916. autoExpandContent() {
  1917. log.info("自动展开全文");
  1918. return [
  1919. CommonUtil.addBlockCSS("div.article-show-more"),
  1920. addStyle(`
  1921. /* 自动展开全文 */
  1922. .main-content .user-article{
  1923. height: auto !important;
  1924. overflow: auto !important;
  1925. }
  1926. `)
  1927. ];
  1928. },
  1929. /**
  1930. * 屏蔽云开发者任务挑战活动
  1931. */
  1932. shieldCloudDeveloperTaskChallengeEvent() {
  1933. log.info("屏蔽云开发者任务挑战活动");
  1934. return CommonUtil.addBlockCSS(".luck-draw-modal-warp");
  1935. },
  1936. /**
  1937. * 屏蔽左侧悬浮按钮
  1938. */
  1939. shieldLeftFloatingButton() {
  1940. log.info("屏蔽左侧悬浮按钮,包括当前阅读量、点赞按钮、评论按钮、分享按钮");
  1941. return CommonUtil.addBlockCSS("div.toolbar-wrapper.article-interact-bar");
  1942. },
  1943. /**
  1944. * 屏蔽右侧栏
  1945. */
  1946. blockRightColumn() {
  1947. log.info("屏蔽右侧栏,包括相关产品-活动日历-运营活动-热门标签");
  1948. return CommonUtil.addBlockCSS("div.page-home-right.dp-aside-right");
  1949. },
  1950. /**
  1951. * 屏蔽底部推荐内容
  1952. */
  1953. blockRecommendedContentAtTheBottom() {
  1954. log.info("屏蔽底部推荐内容");
  1955. return CommonUtil.addBlockCSS("div.recommend-card-box");
  1956. },
  1957. /**
  1958. * 屏蔽底部更多推荐
  1959. */
  1960. shieldTheBottomForMoreRecommendations() {
  1961. log.info("屏蔽底部更多推荐");
  1962. return CommonUtil.addBlockCSS("div.more-article");
  1963. }
  1964. };
  1965. const BlogShieldCSS = ".ecommend-item-box.recommend-recommend-box,\r\n.login-mark,\r\n.opt-box.text-center,\r\n.leftPop,\r\n#csdn-shop-window,\r\n.toolbar-advert,\r\n.hide-article-box,\r\n.user-desc.user-desc-fix,\r\n.recommend-card-box,\r\n.more-article,\r\n.article-show-more,\r\n#csdn-toolbar-profile-nologin,\r\n.guide-rr-first,\r\n#recommend-item-box-tow,\r\n/* 发文章得原力分图片提示 */\r\ndiv.csdn-toolbar-creative-mp,\r\n/* 阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。 */\r\n#toolBarBox div.write-guide-buttom-box,\r\n/* 觉得还不错? 一键收藏 */\r\nul.toolbox-list div.tool-active-list,\r\n/* 右边按钮组的最上面的创作话题 */\r\ndiv.csdn-side-toolbar .activity-swiper-box,\r\n.sidetool-writeguide-box .tip-box,\r\n/* 右下角的登录提示 */\r\n.passport-login-tip-container,\r\n/* 全屏双十一红包 */\r\n.csdn-reapck-select {\r\n display: none !important;\r\n}\r\n";
  1966. const BlogCSS = "/*.blog_container_aside,\r\n#nav {\r\n margin-left: -45px;\r\n}\r\n.recommend-right.align-items-stretch.clearfix,\r\n.dl_right_fixed {\r\n margin-left: 45px;\r\n}*/\r\n";
  1967. const BlogArticleCenterCSS = '#mainBox main {\r\n width: inherit !important;\r\n}\r\n/* 当文章向下滚动时,触发左侧信息悬浮 */\r\naside.blog_container_aside[style*="position: fixed;"] {\r\n display: none !important;\r\n}\r\n\r\n@media (min-width: 1320px) and (max-width: 1380px) {\r\n .nodata .container {\r\n width: 900px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 900px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 490px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 500px;\r\n }\r\n}\r\n\r\n@media screen and (max-width: 1320px) {\r\n .nodata .container {\r\n width: 760px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 760px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 490px !important;\r\n }\r\n\r\n .nodata .container main .toolbox-list .tool-reward {\r\n display: none;\r\n }\r\n\r\n .nodata\r\n .container\r\n main\r\n .more-toolbox-new\r\n .toolbox-left\r\n .profile-box\r\n .profile-name {\r\n max-width: 128px;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 420px;\r\n }\r\n}\r\n\r\n@media screen and (min-width: 1380px) {\r\n .nodata .container {\r\n width: 1010px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 1010px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 490px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 560px;\r\n }\r\n}\r\n\r\n@media (min-width: 1550px) and (max-width: 1700px) {\r\n .nodata .container {\r\n width: 820px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 820px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 690px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 500px;\r\n }\r\n}\r\n\r\n@media screen and (min-width: 1700px) {\r\n .nodata .container {\r\n width: 1010px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 1010px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 690px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 560px;\r\n }\r\n}\r\n';
  1968. const CSDNBlogRightToolBar = {
  1969. init() {
  1970. PopsPanel.execMenuOnce(
  1971. "csdn-blog-rightToolbarEnable",
  1972. () => {
  1973. return this.shieldRightToolbar();
  1974. },
  1975. (_, value) => {
  1976. return !value;
  1977. },
  1978. (_, newValue) => {
  1979. return !newValue;
  1980. }
  1981. );
  1982. PopsPanel.execMenuOnce("csdn-blog-rightToolbarCreativeCenter", () => {
  1983. return this.shieldCreativeCenter();
  1984. });
  1985. PopsPanel.execMenuOnce("csdn-blog-rightToolbarShowOrSidebar", () => {
  1986. return this.shieldShowOrSidebar();
  1987. });
  1988. PopsPanel.execMenuOnce("csdn-blog-rightToolbarBeginnerGuidance", () => {
  1989. return this.shieldBeginnerGuidance();
  1990. });
  1991. PopsPanel.execMenuOnce("csdn-blog-rightToolbarCustomerService", () => {
  1992. return this.shieldCustomerService();
  1993. });
  1994. PopsPanel.execMenuOnce("csdn-blog-rightToolbarReport", () => {
  1995. return this.shieldReport();
  1996. });
  1997. PopsPanel.execMenuOnce("csdn-blog-rightToolbarBackToTop", () => {
  1998. return this.shieldBackToTop();
  1999. });
  2000. this.initRightToolbarOffset();
  2001. domutils.ready(() => {
  2002. PopsPanel.execMenuOnce("csdn-blog-addGotoRecommandButton", () => {
  2003. this.addGotoRecommandButton();
  2004. });
  2005. });
  2006. },
  2007. /**
  2008. * 【添加】前往评论按钮,在返回顶部的下面
  2009. */
  2010. addGotoRecommandButton() {
  2011. log.info("【添加】前往评论按钮,在返回顶部的上面");
  2012. let gotoRecommandNode = document.createElement("a");
  2013. gotoRecommandNode.className = "option-box";
  2014. gotoRecommandNode.setAttribute("data-type", "gorecommand");
  2015. gotoRecommandNode.innerHTML = `<span class="show-txt" style="display:flex;opacity:100;">前往<br>评论</span>`;
  2016. gotoRecommandNode.addEventListener("click", function() {
  2017. let toolbarBoxElement = document.querySelector("#toolBarBox");
  2018. if (!toolbarBoxElement || !toolbarBoxElement.getClientRects().length) {
  2019. let $pcCommentBox = $("#pcCommentBox");
  2020. if ($pcCommentBox && $pcCommentBox.getClientRects().length) {
  2021. toolbarBoxElement = $pcCommentBox;
  2022. } else {
  2023. log.error("评论区处于隐藏状态");
  2024. return;
  2025. }
  2026. }
  2027. log.info("滚动到评论");
  2028. let toolbarBoxOffsetTop = toolbarBoxElement.getBoundingClientRect().top + window.scrollY;
  2029. let csdnToolBarElement = document.querySelector(
  2030. "#csdn-toolbar"
  2031. );
  2032. let csdnToolBarStyles = window.getComputedStyle(csdnToolBarElement);
  2033. let csdnToolBarHeight = csdnToolBarElement.clientHeight - parseFloat(csdnToolBarStyles.paddingTop) - parseFloat(csdnToolBarStyles.paddingBottom);
  2034. window.scrollTo({
  2035. top: toolbarBoxOffsetTop - csdnToolBarHeight - 8,
  2036. left: 0,
  2037. behavior: "smooth"
  2038. });
  2039. });
  2040. utils.waitNode(".csdn-side-toolbar").then(() => {
  2041. let targetElement = document.querySelector(
  2042. ".csdn-side-toolbar a:nth-last-child(2)"
  2043. );
  2044. targetElement.parentElement.insertBefore(
  2045. gotoRecommandNode,
  2046. targetElement.nextSibling
  2047. );
  2048. });
  2049. },
  2050. /**
  2051. * 初始化右侧工具栏的偏移(top、right)
  2052. */
  2053. initRightToolbarOffset() {
  2054. log.info("初始化右侧工具栏的偏移(top、right)");
  2055. addStyle(
  2056. /*css*/
  2057. `
  2058. .csdn-side-toolbar{
  2059. left: unset !important;
  2060. }
  2061. `
  2062. );
  2063. utils.waitNode(".csdn-side-toolbar").then(($sideToolbar) => {
  2064. domutils.css($sideToolbar, {
  2065. top: parseInt(PopsPanel.getValue("csdn-blog-rightToolbarTopOffset")) + "px",
  2066. right: parseInt(PopsPanel.getValue("csdn-blog-rightToolbarRightOffset")) + "px"
  2067. });
  2068. });
  2069. },
  2070. /**
  2071. * 屏蔽右侧工具栏
  2072. */
  2073. shieldRightToolbar() {
  2074. log.info("屏蔽右侧工具栏");
  2075. return CommonUtil.addBlockCSS(`div.csdn-side-toolbar`);
  2076. },
  2077. /**
  2078. * 【屏蔽】创作中心
  2079. */
  2080. shieldCreativeCenter() {
  2081. log.info("【屏蔽】创作中心");
  2082. return CommonUtil.addBlockCSS(".csdn-side-toolbar .sidetool-writeguide-box");
  2083. },
  2084. /**
  2085. * 【屏蔽】显示/隐藏侧栏
  2086. */
  2087. shieldShowOrSidebar() {
  2088. log.info("【屏蔽】显示/隐藏侧栏");
  2089. return CommonUtil.addBlockCSS(".csdn-side-toolbar a.sidecolumn");
  2090. },
  2091. /**
  2092. * 【屏蔽】新手引导
  2093. */
  2094. shieldBeginnerGuidance() {
  2095. log.info("【屏蔽】新手引导");
  2096. return CommonUtil.addBlockCSS(
  2097. '.csdn-side-toolbar a.option-box[data-type="guide"]'
  2098. );
  2099. },
  2100. /**
  2101. * 【屏蔽】客服
  2102. */
  2103. shieldCustomerService() {
  2104. log.info("【屏蔽】客服");
  2105. return CommonUtil.addBlockCSS(
  2106. '.csdn-side-toolbar a.option-box[data-type="cs"]'
  2107. );
  2108. },
  2109. /**
  2110. * 【屏蔽】举报
  2111. */
  2112. shieldReport() {
  2113. log.info("【屏蔽】举报");
  2114. return CommonUtil.addBlockCSS(
  2115. '.csdn-side-toolbar a.option-box[data-type="report"]'
  2116. );
  2117. },
  2118. /**
  2119. * 【屏蔽】返回顶部
  2120. */
  2121. shieldBackToTop() {
  2122. log.info("【屏蔽】返回顶部");
  2123. return CommonUtil.addBlockCSS(
  2124. '.csdn-side-toolbar a.option-box[data-type="gotop"]'
  2125. );
  2126. }
  2127. };
  2128. const CSDNBlog = {
  2129. init() {
  2130. this.addCSS();
  2131. CSDNBlogRightToolBar.init();
  2132. PopsPanel.execMenuOnce("csdn-blog-articleCenter", () => {
  2133. return this.articleCenter();
  2134. });
  2135. PopsPanel.execMenuOnce("csdn-blog-shieldLoginDialog", () => {
  2136. return this.shieldLoginDialog();
  2137. });
  2138. PopsPanel.execMenuOnce("csdn-blog-autoExpandContent", () => {
  2139. return this.autoExpandContent();
  2140. });
  2141. PopsPanel.execMenuOnce("csdn-blog-autoExpandCodeContent", () => {
  2142. return this.autoExpandCodeContent();
  2143. });
  2144. PopsPanel.execMenuOnce(
  2145. "csdn-blog-blockComment",
  2146. () => {
  2147. return this.blockComment();
  2148. },
  2149. (_, value) => {
  2150. return !value;
  2151. },
  2152. (_, newValue) => {
  2153. return !newValue;
  2154. }
  2155. );
  2156. PopsPanel.execMenuOnce(
  2157. "csdn-blog-bottomRecommendArticleEnable",
  2158. () => {
  2159. return this.shieldBottomRecommendArticle();
  2160. },
  2161. (_, value) => {
  2162. return !value;
  2163. },
  2164. (_, newValue) => {
  2165. return !newValue;
  2166. }
  2167. );
  2168. PopsPanel.execMenuOnce("csdn-blog-shieldBottomSkillTree", () => {
  2169. return this.shieldBottomSkillTree();
  2170. });
  2171. PopsPanel.execMenuOnce("csdn-blog-shieldBottomFloatingToolbar", () => {
  2172. return this.shieldBottomFloatingToolbar();
  2173. });
  2174. PopsPanel.execMenuOnce("csdn-blog-shieldLeftBlogContainerAside", () => {
  2175. return this.shieldLeftBlogContainerAside();
  2176. });
  2177. PopsPanel.execMenuOnce("csdn-blog-shieldRightDirectoryInformation", () => {
  2178. return this.shieldRightDirectoryInformation();
  2179. });
  2180. PopsPanel.execMenuOnce("csdn-blog-shieldTopToolbar", () => {
  2181. return this.shieldTopToolbar();
  2182. });
  2183. PopsPanel.execMenuOnce("csdn-blog-shieldArticleSearchTip", () => {
  2184. return this.shieldArticleSearchTip();
  2185. });
  2186. PopsPanel.execMenuOnce("csdn-blog-allowSelectContent", () => {
  2187. return this.allowSelectContent();
  2188. });
  2189. domutils.ready(() => {
  2190. PopsPanel.execMenuOnce("csdn-blog-removeClipboardHijacking", () => {
  2191. this.removeClipboardHijacking();
  2192. });
  2193. PopsPanel.execMenuOnce("csdn-blog-unBlockCopy", () => {
  2194. this.unBlockCopy();
  2195. });
  2196. PopsPanel.execMenuOnce("csdn-blog-identityCSDNDownload", () => {
  2197. this.identityCSDNDownload();
  2198. });
  2199. PopsPanel.execMenuOnce("csdn-blog-clickPreCodeAutomatically", () => {
  2200. this.clickPreCodeAutomatically();
  2201. });
  2202. PopsPanel.execMenuOnce("csdn-blog-restoreComments", () => {
  2203. this.restoreComments();
  2204. });
  2205. });
  2206. },
  2207. /**
  2208. * 添加屏蔽CSS和功能CSS
  2209. */
  2210. addCSS() {
  2211. log.info("添加屏蔽CSS和功能CSS");
  2212. return [addStyle(BlogShieldCSS), addStyle(BlogCSS)];
  2213. },
  2214. /**
  2215. * 去除剪贴板劫持
  2216. */
  2217. removeClipboardHijacking() {
  2218. log.info("去除剪贴板劫持");
  2219. let $article_copyright = document.querySelector(".article-copyright");
  2220. if ($article_copyright) {
  2221. $article_copyright.remove();
  2222. }
  2223. if (_unsafeWindow.articleType) {
  2224. _unsafeWindow.articleType = 0;
  2225. }
  2226. if (_unsafeWindow.csdn && _unsafeWindow.csdn.copyright && _unsafeWindow.csdn.copyright.textData) {
  2227. _unsafeWindow.csdn.copyright.textData = "";
  2228. }
  2229. if (_unsafeWindow.csdn && _unsafeWindow.csdn.copyright && _unsafeWindow.csdn.copyright.htmlData) {
  2230. _unsafeWindow.csdn.copyright.htmlData = "";
  2231. }
  2232. },
  2233. /**
  2234. * 取消禁止复制
  2235. */
  2236. unBlockCopy() {
  2237. log.info("取消禁止复制");
  2238. domutils.on(
  2239. document,
  2240. "click",
  2241. function(event) {
  2242. let $click = event.target;
  2243. let $parent = $click.parentElement;
  2244. if (!$click.classList.contains("hljs-button")) {
  2245. return;
  2246. }
  2247. utils.preventEvent(event);
  2248. let copyText = ($parent.innerText || $parent.textContent || "").toString();
  2249. log.info(
  2250. "点击复制按钮复制内容:" + (copyText.length > 8 ? copyText.substring(0, 8) + "..." : copyText)
  2251. );
  2252. utils.setClip(copyText);
  2253. $click.setAttribute("data-title", "复制成功");
  2254. },
  2255. {
  2256. capture: true
  2257. }
  2258. );
  2259. let changeDataTitle = new utils.LockFunction(function(event) {
  2260. let $mouse = event.target;
  2261. if ($mouse.localName !== "pre") {
  2262. return;
  2263. }
  2264. let $hljsBtn = $mouse.querySelector(".hljs-button");
  2265. if ($hljsBtn) {
  2266. $hljsBtn.setAttribute("data-title", "复制");
  2267. }
  2268. });
  2269. domutils.on(
  2270. document,
  2271. ["mouseenter", "mouseleave"],
  2272. function(event) {
  2273. changeDataTitle.run(event);
  2274. },
  2275. {
  2276. capture: true
  2277. }
  2278. );
  2279. utils.waitNode("#content_views").then(($content_views) => {
  2280. var _a2;
  2281. if (_unsafeWindow.$) {
  2282. (_a2 = _unsafeWindow.$("#content_views")) == null ? void 0 : _a2.unbind("copy");
  2283. }
  2284. domutils.on(
  2285. $content_views,
  2286. "copy",
  2287. function(event) {
  2288. utils.preventEvent(event);
  2289. let selectText = _unsafeWindow.getSelection();
  2290. let copyText = selectText == null ? void 0 : selectText.toString();
  2291. log.info(
  2292. "Ctrl+C复制内容:" + (copyText.length > 8 ? copyText.substring(0, 8) + "..." : copyText)
  2293. );
  2294. utils.setClip(copyText);
  2295. return false;
  2296. },
  2297. {
  2298. capture: true
  2299. }
  2300. );
  2301. });
  2302. utils.waitNode(".hljs-button").then(() => {
  2303. setTimeout(() => {
  2304. document.querySelectorAll(".hljs-button").forEach((element) => {
  2305. element.removeAttribute("onclick");
  2306. element.removeAttribute("data-report-click");
  2307. element.setAttribute("data-title", "复制");
  2308. });
  2309. }, 250);
  2310. });
  2311. },
  2312. /**
  2313. * 点击代码块自动展开
  2314. */
  2315. clickPreCodeAutomatically() {
  2316. log.info("点击代码块自动展开");
  2317. document.addEventListener("click", function(event) {
  2318. var _a2;
  2319. let $click = event.target;
  2320. if ($click.localName !== "pre") {
  2321. return;
  2322. }
  2323. $click.style.setProperty("height", "auto");
  2324. (_a2 = $click.querySelector(".hide-preCode-box")) == null ? void 0 : _a2.remove();
  2325. });
  2326. },
  2327. /**
  2328. * 恢复评论到正确位置
  2329. */
  2330. restoreComments() {
  2331. log.info("恢复评论到正确位置-第一条评论");
  2332. utils.waitNode(".first-recommend-box").then(($firstRecommendBox) => {
  2333. let recommendBoxElement = document.querySelector(
  2334. ".recommend-box.insert-baidu-box.recommend-box-style"
  2335. );
  2336. recommendBoxElement.insertBefore(
  2337. $firstRecommendBox,
  2338. recommendBoxElement.firstChild
  2339. );
  2340. });
  2341. log.info("恢复评论到正确位置-第二条评论");
  2342. utils.waitNode(".second-recommend-box").then(($secondRecommendBox) => {
  2343. let recommendBoxElement = document.querySelector(
  2344. ".recommend-box.insert-baidu-box.recommend-box-style"
  2345. );
  2346. recommendBoxElement.insertBefore(
  2347. $secondRecommendBox,
  2348. recommendBoxElement.firstChild
  2349. );
  2350. });
  2351. },
  2352. /**
  2353. * 标识CSDN下载的链接
  2354. */
  2355. identityCSDNDownload() {
  2356. log.info("标识CSDN下载的链接");
  2357. document.querySelectorAll(
  2358. ".recommend-item-box[data-url*='https://download.csdn.net/']"
  2359. ).forEach((item) => {
  2360. if (PopsPanel.getValue("csdn-blog-removeResourceDownloadArticle")) {
  2361. item.remove();
  2362. } else {
  2363. item.querySelector(".content-box").style.setProperty("border", "2px solid red");
  2364. }
  2365. });
  2366. },
  2367. /**
  2368. * 全文居中
  2369. */
  2370. articleCenter() {
  2371. log.info("全文居中");
  2372. return addStyle(BlogArticleCenterCSS);
  2373. },
  2374. /**
  2375. * 屏蔽登录弹窗
  2376. */
  2377. shieldLoginDialog() {
  2378. log.info("屏蔽登录弹窗");
  2379. return CommonUtil.addBlockCSS(`.passport-login-container`);
  2380. },
  2381. /**
  2382. * 自动展开代码块
  2383. */
  2384. autoExpandCodeContent() {
  2385. log.info("自动展开代码块");
  2386. return [
  2387. CommonUtil.addBlockCSS("pre.set-code-hide .hide-preCode-box"),
  2388. addStyle(
  2389. /*css*/
  2390. `
  2391. pre.set-code-hide{
  2392. height: auto !important;
  2393. }
  2394. /* 自动展开代码块 */
  2395. .comment-list-box,
  2396. main div.blog-content-box pre {
  2397. max-height: none !important;
  2398. }
  2399. `
  2400. )
  2401. ];
  2402. },
  2403. /**
  2404. * 自动展开全文
  2405. */
  2406. autoExpandContent() {
  2407. log.info("自动展开全文");
  2408. return addStyle(
  2409. /*css*/
  2410. `
  2411. /* 自动展开全文 */
  2412. #article_content,
  2413. .user-article.user-article-hide {
  2414. height: auto !important;
  2415. overflow: auto !important;
  2416. }
  2417. `
  2418. );
  2419. },
  2420. /**
  2421. * 屏蔽评论区
  2422. */
  2423. blockComment() {
  2424. log.info("屏蔽评论区");
  2425. return CommonUtil.addBlockCSS(`#pcCommentBox`);
  2426. },
  2427. /**
  2428. * 屏蔽底部推荐文章
  2429. */
  2430. shieldBottomRecommendArticle() {
  2431. log.info("屏蔽底部推荐文章");
  2432. return CommonUtil.addBlockCSS(`main > div.recommend-box`);
  2433. },
  2434. /**
  2435. * 屏蔽底部xx技能树
  2436. */
  2437. shieldBottomSkillTree() {
  2438. log.info("屏蔽底部xx技能树");
  2439. return CommonUtil.addBlockCSS(`#treeSkill`);
  2440. },
  2441. /**
  2442. * 屏蔽底部悬浮工具栏
  2443. */
  2444. shieldBottomFloatingToolbar() {
  2445. log.info("屏蔽底部悬浮工具栏");
  2446. return CommonUtil.addBlockCSS(`#toolBarBox`);
  2447. },
  2448. /**
  2449. * 屏蔽左侧博客信息
  2450. */
  2451. shieldLeftBlogContainerAside() {
  2452. log.info("【屏蔽】左侧博客信息");
  2453. return CommonUtil.addBlockCSS(`aside.blog_container_aside`);
  2454. },
  2455. /**
  2456. * 【屏蔽】右侧目录信息
  2457. */
  2458. shieldRightDirectoryInformation() {
  2459. log.info("【屏蔽】右侧目录信息");
  2460. return CommonUtil.addBlockCSS("#rightAsideConcision", "#rightAside");
  2461. },
  2462. /**
  2463. * 屏蔽顶部Toolbar
  2464. */
  2465. shieldTopToolbar() {
  2466. log.info("屏蔽顶部Toolbar");
  2467. return CommonUtil.addBlockCSS(`#toolbarBox`);
  2468. },
  2469. /**
  2470. * 屏蔽文章内的选中搜索悬浮提示
  2471. */
  2472. shieldArticleSearchTip() {
  2473. log.info("屏蔽文章内的选中搜索悬浮提示");
  2474. return CommonUtil.addBlockCSS(`#articleSearchTip`);
  2475. },
  2476. /**
  2477. * 允许选择内容
  2478. */
  2479. allowSelectContent() {
  2480. log.info("允许选择内容");
  2481. return addStyle(
  2482. /*css*/
  2483. `
  2484. #content_views,
  2485. #content_views pre,
  2486. #content_views pre code {
  2487. user-select: text !important;
  2488. }
  2489. `
  2490. );
  2491. }
  2492. };
  2493. const WenkuCSS = "#chatgpt-article-detail\r\n > div.layout-center\r\n > div.main\r\n > div.article-box\r\n > div.cont.first-show.forbid {\r\n max-height: unset !important;\r\n height: auto !important;\r\n overflow: auto !important;\r\n}\r\n\r\n.forbid {\r\n user-select: text !important;\r\n}\r\n";
  2494. const ShieldCSS$3 = "/* wenku顶部横幅 */\r\n#app > div > div.main.pb-32 > div > div.top-bar,\r\n/* 底部展开全文 */\r\n#chatgpt-article-detail > div.layout-center > div.main > div.article-box > div.cont.first-show.forbid > div.open {\r\n display: none !important;\r\n}";
  2495. const CSDNWenKu = {
  2496. init() {
  2497. addStyle(WenkuCSS);
  2498. addStyle(ShieldCSS$3);
  2499. PopsPanel.execMenuOnce("csdn-wenku-shieldResourceRecommend", () => {
  2500. return this.shieldResourceRecommend();
  2501. });
  2502. PopsPanel.execMenuOnce("csdn-wenku-shieldRightUserInfo", () => {
  2503. return this.shieldRightUserInfo();
  2504. });
  2505. PopsPanel.execMenuOnce("csdn-wenku-shieldRightToolBar", () => {
  2506. return this.shieldRightToolBar();
  2507. });
  2508. },
  2509. /**
  2510. * 【屏蔽】资源推荐
  2511. */
  2512. shieldResourceRecommend() {
  2513. log.info("【屏蔽】资源推荐");
  2514. return CommonUtil.addBlockCSS("#recommend");
  2515. },
  2516. /**
  2517. * 【屏蔽】右侧用户信息
  2518. */
  2519. shieldRightUserInfo() {
  2520. log.info("【屏蔽】右侧用户信息");
  2521. return CommonUtil.addBlockCSS(".layout-right");
  2522. },
  2523. /**
  2524. * 【屏蔽】右侧悬浮工具栏
  2525. */
  2526. shieldRightToolBar() {
  2527. log.info("【屏蔽】右侧悬浮工具栏");
  2528. return CommonUtil.addBlockCSS(".csdn-side-toolbar");
  2529. }
  2530. };
  2531. const CSDNLink = {
  2532. init() {
  2533. PopsPanel.execMenuOnce("csdn-link-jumpRedirect", () => {
  2534. this.jumpRedirect();
  2535. });
  2536. },
  2537. /**
  2538. * 去除CSDN拦截其它网址的url并自动跳转
  2539. * @example
  2540. * https://link.csdn.net/?target=https%3A%2F%2Fjaist.dl.sourceforge.net%2Fproject%2Fportecle%2Fv1.11%2Fportecle-1.11.zip
  2541. */
  2542. jumpRedirect() {
  2543. try {
  2544. let urlSearchParams = new URLSearchParams(window.location.search);
  2545. const URL_KEY = "target";
  2546. if (urlSearchParams.has(URL_KEY)) {
  2547. let target = urlSearchParams.get(URL_KEY);
  2548. let jumpUrl = decodeURIComponent(target);
  2549. log.success(`跳转链接:${jumpUrl}`);
  2550. window.location.href = jumpUrl;
  2551. } else {
  2552. log.error("解析跳转的链接失败,原因:搜索参数中没有target参数");
  2553. }
  2554. } catch (error) {
  2555. Qmsg.error("跳转链接失败:" + error.message);
  2556. }
  2557. }
  2558. };
  2559. const CSDN = {
  2560. init() {
  2561. if (CSDNRouter.isLink()) {
  2562. log.info("Router: 中转链接");
  2563. CSDNLink.init();
  2564. } else if (CSDNRouter.isHuaWeiCloudBlog()) {
  2565. log.info("Router: 华为云联盟");
  2566. CSDNHuaWeiCloud.init();
  2567. } else if (CSDNRouter.isBlog()) {
  2568. log.info("Router: 博客");
  2569. CSDNBlog.init();
  2570. } else if (CSDNRouter.isWenKu()) {
  2571. log.info("Router: 文库");
  2572. CSDNWenKu.init();
  2573. } else {
  2574. log.error("暂未适配,请反馈开发者:" + globalThis.location.href);
  2575. }
  2576. }
  2577. };
  2578. const M_CSDNLink = {
  2579. init() {
  2580. PopsPanel.execMenuOnce("m-csdn-link-jumpRedirect", () => {
  2581. CSDNLink.jumpRedirect();
  2582. });
  2583. }
  2584. };
  2585. const ShieldCSS$2 = "/* 右下角的 免费赢华为平板xxxx */\r\n.org-main-content .siderbar-box {\r\n display: none !important;\r\n}\r\n";
  2586. const M_CSDNHuaWeiCloud = {
  2587. init() {
  2588. addStyle(ShieldCSS$2);
  2589. PopsPanel.execMenuOnce("m-csdn-hua-wei-cloud-autoExpandContent", () => {
  2590. return CSDNHuaWeiCloud.autoExpandContent();
  2591. });
  2592. PopsPanel.execMenuOnce(
  2593. "m-csdn-hua-wei-cloud-blockBottomJoinTheCommunity",
  2594. () => {
  2595. return this.blockBottomJoinTheCommunity();
  2596. }
  2597. );
  2598. },
  2599. /**
  2600. * 【屏蔽】底部加入社区
  2601. */
  2602. blockBottomJoinTheCommunity() {
  2603. log.info("【屏蔽】底部加入社区");
  2604. return CommonUtil.addBlockCSS(".user-desc");
  2605. }
  2606. };
  2607. const ShieldCSS$1 = ".view_comment_box,\r\n.weixin-shadowbox.wap-shadowbox,\r\n.feed-Sign-span,\r\n.user-desc.user-desc-fix,\r\n.comment_read_more_box,\r\n#content_views pre.set-code-hide .hide-preCode-box,\r\n/* 登录弹窗 */\r\n.passport-login-container,\r\n.hljs-button[data-title='登录后复制'],\r\n.article-show-more,\r\n#treeSkill,\r\ndiv.btn_open_app_prompt_div,\r\ndiv.readall_box,\r\ndiv.aside-header-fixed,\r\ndiv.feed-Sign-weixin,\r\ndiv.ios-shadowbox {\r\n display: none !important;\r\n}\r\n";
  2608. const MBlogCSS = "#mainBox {\r\n width: auto;\r\n}\r\n.user-desc.user-desc-fix {\r\n height: auto !important;\r\n overflow: auto !important;\r\n}\r\n.component-box .praise {\r\n background: #ff5722;\r\n border-radius: 5px;\r\n padding: 0px 8px;\r\n height: auto;\r\n}\r\n.component-box .praise,\r\n.component-box .share {\r\n color: #fff;\r\n}\r\n.component-box a {\r\n display: inline-block;\r\n font-size: xx-small;\r\n}\r\n.component-box {\r\n display: inline;\r\n margin: 0;\r\n position: relative;\r\n white-space: nowrap;\r\n}\r\n.csdn-edu-title {\r\n background: #4d6de1;\r\n border-radius: 5px;\r\n padding: 0px 8px;\r\n height: auto;\r\n color: #fff !important;\r\n}\r\n\r\n.GM-csdn-dl {\r\n padding: 0.24rem 0.32rem;\r\n width: 100%;\r\n justify-content: space-between;\r\n -webkit-box-pack: justify;\r\n border-bottom: 1px solid #f5f6f7 !important;\r\n}\r\n.GM-csdn-title {\r\n font-size: 0.3rem;\r\n color: #222226;\r\n letter-spacing: 0;\r\n line-height: 0.44rem;\r\n font-weight: 600;\r\n /*max-height: .88rem;*/\r\n word-break: break-all;\r\n overflow: hidden;\r\n display: -webkit-box;\r\n -webkit-box-orient: vertical;\r\n -webkit-line-clamp: 2;\r\n}\r\n.GM-csdn-title a {\r\n word-break: break-all;\r\n color: #222226;\r\n font-weight: 600;\r\n}\r\n.GM-csdn-title em,\r\n.GM-csdn-content em {\r\n font-style: normal;\r\n color: #fc5531;\r\n}\r\n.GM-csdn-content {\r\n /*max-width: 5.58rem;*/\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 1;\r\n -webkit-box-orient: vertical;\r\n color: #555666;\r\n font-size: 0.24rem;\r\n line-height: 0.34rem;\r\n max-height: 0.34rem;\r\n word-break: break-all;\r\n -webkit-box-flex: 1;\r\n -ms-flex: 1;\r\n flex: 1;\r\n margin-top: 0.16rem;\r\n}\r\n.GM-csdn-img img {\r\n width: 2.18rem;\r\n height: 1.58rem;\r\n /*margin-left: .16rem*/\r\n}\r\n";
  2609. const ApiResponseCheck = {
  2610. isSuccessResponse(data) {
  2611. if (data == null) {
  2612. return false;
  2613. }
  2614. if (typeof data === "string") {
  2615. data = utils.toJSON(data);
  2616. }
  2617. return (data == null ? void 0 : data.code) === 200;
  2618. }
  2619. };
  2620. const CSDNFavoriteApi = {
  2621. /**
  2622. * 获取收藏夹信息
  2623. * @param url 当前url
  2624. */
  2625. async folderListWithCheck(url) {
  2626. let response = await httpx.get(
  2627. `https://mp-action.csdn.net/interact/wrapper/pc/favorite/v1/api/folderListWithCheck`,
  2628. {
  2629. data: {
  2630. url
  2631. },
  2632. fetch: true,
  2633. allowInterceptConfig: false,
  2634. headers: {
  2635. "User-Agent": utils.getRandomPCUA()
  2636. }
  2637. }
  2638. );
  2639. if (!response.status || !ApiResponseCheck.isSuccessResponse(response.data.responseText)) {
  2640. log.error("获取收藏夹信息失败,请求异常", response);
  2641. Qmsg.error("获取收藏夹信息失败");
  2642. return;
  2643. }
  2644. let data = utils.toJSON(response.data.responseText);
  2645. return data.data.result;
  2646. },
  2647. /**
  2648. * 添加到某个收藏夹
  2649. */
  2650. async addFavoriteInFolds(requestData) {
  2651. let response = await httpx.post(
  2652. "https://mp-action.csdn.net/interact/wrapper/pc/favorite/v1/api/addFavoriteInFolds",
  2653. {
  2654. fetch: true,
  2655. data: requestData,
  2656. headers: {
  2657. "Content-Type": "application/json",
  2658. "User-Agent": utils.getRandomPCUA()
  2659. },
  2660. allowInterceptConfig: false
  2661. }
  2662. );
  2663. if (!response.status || !ApiResponseCheck.isSuccessResponse(response.data.responseText)) {
  2664. log.error("添加收藏失败,请求异常", response);
  2665. Qmsg.error("添加收藏失败,请求异常");
  2666. return;
  2667. }
  2668. return true;
  2669. },
  2670. /**
  2671. * 检查收藏夹信息
  2672. * @param url
  2673. * @returns
  2674. * + true 已收藏
  2675. * + false 未收藏
  2676. */
  2677. async checkFavoriteByUrl(url) {
  2678. debugger;
  2679. let response = await httpx.get(
  2680. `https://mp-action.csdn.net/interact/wrapper/pc/favorite/v1/api/checkFavoriteByUrl`,
  2681. {
  2682. data: {
  2683. url
  2684. },
  2685. fetch: true,
  2686. allowInterceptConfig: false,
  2687. headers: {
  2688. "User-Agent": utils.getRandomPCUA()
  2689. }
  2690. }
  2691. );
  2692. if (!response.status || !ApiResponseCheck.isSuccessResponse(response.data.responseText)) {
  2693. log.error("检查收藏夹状态失败,请求异常", response);
  2694. Qmsg.error("检查收藏夹状态失败,请求异常");
  2695. return;
  2696. }
  2697. let data = utils.toJSON(response.data.responseText);
  2698. return data.data;
  2699. }
  2700. };
  2701. const M_CSDNBlog = {
  2702. init() {
  2703. this.addCSS();
  2704. PopsPanel.execMenuOnce(
  2705. "m-csdn-blog-shieldTopToolbar",
  2706. () => {
  2707. return this.shieldTopToolbar();
  2708. },
  2709. (_, value) => !value,
  2710. (_, value) => !value
  2711. );
  2712. PopsPanel.execMenuOnce("m-csdn-blog-notLimitCodePreMaxHeight", () => {
  2713. return this.notLimitCodePreMaxHeight();
  2714. });
  2715. PopsPanel.execMenuOnce("m-csdn-blog-notLimitCommentMaxHeight", () => {
  2716. return this.notLimitCommentMaxHeight();
  2717. });
  2718. PopsPanel.execMenuOnce("m-csdn-blog-allowSelectText", () => {
  2719. return this.allowSelectText();
  2720. });
  2721. PopsPanel.execMenuOnce("m-csdn-blog-autoExpandContent", () => {
  2722. return this.autoExpandContent();
  2723. });
  2724. PopsPanel.execMenuOnce(
  2725. "m-csdn-blog-bottomArticleEnable",
  2726. () => {
  2727. return this.blockBottomArticle();
  2728. },
  2729. (_, value) => !value,
  2730. (_, value) => !value
  2731. );
  2732. PopsPanel.execMenuOnce(
  2733. "m-csdn-blog-comment-enable",
  2734. () => {
  2735. return this.blockComment();
  2736. },
  2737. (_, value) => !value,
  2738. (_, value) => !value
  2739. );
  2740. PopsPanel.execMenuOnce(
  2741. "m-csdn-blog-bottom-toolbar-enable",
  2742. () => {
  2743. return this.blockBottomToolBar();
  2744. },
  2745. (_, value) => !value,
  2746. (_, value) => !value
  2747. );
  2748. PopsPanel.execMenuOnce("m-csdn-blog-bottom-toolbar-always-bottom", () => {
  2749. return this.bottomToolBarAlwaysShow();
  2750. });
  2751. domutils.ready(() => {
  2752. PopsPanel.execMenuOnce("m-csdn-blog-removeAds", () => {
  2753. return this.removeAds();
  2754. });
  2755. PopsPanel.execMenuOnce("m-csdn-blog-refactoringRecommendation", () => {
  2756. this.refactoringRecommendation();
  2757. });
  2758. PopsPanel.execMenuOnce("m-csdn-blog-unBlockCopy", () => {
  2759. CSDNBlog.unBlockCopy();
  2760. });
  2761. PopsPanel.execMenuOnce(
  2762. "m-csdn-blog-bottom-toolbar-optimizationCollectButton",
  2763. () => {
  2764. this.optimizationCollectButton();
  2765. }
  2766. );
  2767. });
  2768. },
  2769. addCSS() {
  2770. addStyle(ShieldCSS$1);
  2771. addStyle(MBlogCSS);
  2772. },
  2773. /**
  2774. * 屏蔽顶部Toolbar
  2775. */
  2776. shieldTopToolbar() {
  2777. log.info("屏蔽顶部Toolbar");
  2778. return [
  2779. CommonUtil.addBlockCSS("#csdn-toolbar"),
  2780. addStyle(
  2781. /*css*/
  2782. `
  2783. /* 内容顶部要归位 */
  2784. body #main,
  2785. .margin_sides{
  2786. margin-top: unset !important;
  2787. padding-top: unset !important;
  2788. }
  2789. #article .article_title{
  2790. margin-top: .32rem !important;
  2791. padding-top: unset !important;
  2792. }
  2793. `
  2794. )
  2795. ];
  2796. },
  2797. /**
  2798. * 重构底部推荐
  2799. */
  2800. refactoringRecommendation() {
  2801. function refactoring() {
  2802. document.querySelectorAll(".container-fluid").forEach((item) => {
  2803. var _a2, _b;
  2804. let url = "";
  2805. let title = "";
  2806. let content = "";
  2807. let img = "";
  2808. let isCSDNDownload = false;
  2809. let isCSDNEduDownload = false;
  2810. if (item.hasAttribute("data-url")) {
  2811. url = item.getAttribute("data-url");
  2812. title = (_a2 = item.querySelector(".recommend_title div.left")) == null ? void 0 : _a2.innerHTML;
  2813. if (!item.querySelector(".text")) {
  2814. return;
  2815. }
  2816. content = (_b = item.querySelector(".text")) == null ? void 0 : _b.innerHTML;
  2817. if (item.querySelectorAll(".recommend-img").length) {
  2818. item.querySelectorAll(".recommend-img").forEach((item2) => {
  2819. img += item2.innerHTML;
  2820. });
  2821. }
  2822. } else {
  2823. url = item.querySelector("a[data-type]").getAttribute("href");
  2824. title = item.querySelector(".recommend_title div.left").innerHTML;
  2825. content = item.querySelector(".text").innerHTML;
  2826. }
  2827. var _URL_ = new URL(url);
  2828. if (_URL_.host === "download.csdn.net" || _URL_.host === "www.iteye.com" && _URL_.pathname.match(/^\/resource/gi)) {
  2829. isCSDNDownload = true;
  2830. title = `<div class="component-box"><a class="praise" href="javascript:;">CSDN下载</a></div>` + title;
  2831. } else if (_URL_.origin.match(/edu.csdn.net/gi)) {
  2832. isCSDNEduDownload = true;
  2833. title = `<div class="component-box"><a class="csdn-edu-title" href="javascript:;">CSDN学院</a></div>` + title;
  2834. }
  2835. item.setAttribute("class", "GM-csdn-dl");
  2836. item.setAttribute("data-url", url);
  2837. item.innerHTML = `<div class="GM-csdn-title"><div class="left">${title}</div></div><div class="GM-csdn-content">${content}</div><div class="GM-csdn-img">${img}</div>`;
  2838. item.addEventListener("click", function() {
  2839. if (PopsPanel.getValue("m-csdn-blog-openNewTab")) {
  2840. window.open(url, "_blank");
  2841. } else {
  2842. window.location.href = url;
  2843. }
  2844. });
  2845. if ((isCSDNDownload || isCSDNEduDownload) && PopsPanel.getValue("m-csdn-blog-removeResourceArticle")) {
  2846. item.remove();
  2847. }
  2848. });
  2849. }
  2850. let lockFunction = new utils.LockFunction(refactoring, 50);
  2851. utils.waitNode("#recommend").then(($recommend) => {
  2852. log.info("重构底部推荐");
  2853. lockFunction.run();
  2854. utils.mutationObserver($recommend, {
  2855. callback: () => {
  2856. lockFunction.run();
  2857. },
  2858. config: { childList: true, subtree: true, attributes: true }
  2859. });
  2860. });
  2861. },
  2862. /**
  2863. * 屏蔽底部文章
  2864. */
  2865. blockBottomArticle() {
  2866. log.info("屏蔽底部文章");
  2867. return CommonUtil.addBlockCSS("#recommend");
  2868. },
  2869. /**
  2870. * 屏蔽评论
  2871. */
  2872. blockComment() {
  2873. log.info("屏蔽评论");
  2874. return CommonUtil.addBlockCSS("#comment");
  2875. },
  2876. /**
  2877. * 去除广告
  2878. */
  2879. removeAds() {
  2880. log.info("去除广告");
  2881. CommonUtil.waitRemove(".passport-login-container");
  2882. CommonUtil.waitRemove(".btn_open_app_prompt_box.detail-open-removed");
  2883. CommonUtil.waitRemove(".add-firstAd");
  2884. CommonUtil.waitRemove("div.feed-Sign-weixin");
  2885. CommonUtil.waitRemove("div.ios-shadowbox");
  2886. },
  2887. /**
  2888. * 不限制代码块最大高度
  2889. */
  2890. notLimitCodePreMaxHeight() {
  2891. log.info("不限制代码块最大高度");
  2892. return addStyle(
  2893. /*css*/
  2894. `
  2895. pre{
  2896. max-height: unset !important;
  2897. }
  2898. `
  2899. );
  2900. },
  2901. /**
  2902. * 不限制评论区最大高度
  2903. */
  2904. notLimitCommentMaxHeight() {
  2905. log.info("不限制评论区最大高度");
  2906. return addStyle(
  2907. /*css*/
  2908. `
  2909. #comment{
  2910. max-height: none !important;
  2911. }
  2912. `
  2913. );
  2914. },
  2915. /**
  2916. * 允许选择文字
  2917. */
  2918. allowSelectText() {
  2919. log.info("允许选择文字");
  2920. return addStyle(
  2921. /*css*/
  2922. `
  2923. #content_views,
  2924. #content_views pre,
  2925. #content_views pre code{
  2926. webkit-touch-callout: text !important;
  2927. -webkit-user-select: text !important;
  2928. -khtml-user-select: text !important;
  2929. -moz-user-select: text !important;
  2930. -ms-user-select: text !important;
  2931. user-select: text !important;
  2932. }
  2933. `
  2934. );
  2935. },
  2936. /**
  2937. * 自动展开内容
  2938. */
  2939. autoExpandContent() {
  2940. log.info("自动展开内容");
  2941. return addStyle(
  2942. /*css*/
  2943. `
  2944. #content_views pre.set-code-hide,
  2945. .article_content{
  2946. height: 100% !important;
  2947. overflow: auto !important;
  2948. }
  2949. `
  2950. );
  2951. },
  2952. /**
  2953. * 屏蔽底部工具栏
  2954. */
  2955. blockBottomToolBar() {
  2956. log.info(`屏蔽底部工具栏`);
  2957. return CommonUtil.addBlockCSS("#operate");
  2958. },
  2959. /**
  2960. * 底部工具栏常驻
  2961. */
  2962. bottomToolBarAlwaysShow() {
  2963. log.info(`底部工具栏常驻`);
  2964. return addStyle(
  2965. /*css*/
  2966. `
  2967. /* 底部工具栏 */
  2968. #operate {
  2969. bottom: 0 !important;
  2970. }
  2971. `
  2972. );
  2973. },
  2974. /**
  2975. * 优化收藏按钮
  2976. */
  2977. optimizationCollectButton() {
  2978. log.info(`优化收藏按钮`);
  2979. utils.waitNode("#operate .collect-btn", 1e4).then(($collectBtn) => {
  2980. if (!$collectBtn) {
  2981. return;
  2982. }
  2983. domutils.on(
  2984. $collectBtn,
  2985. "click",
  2986. async (event) => {
  2987. utils.preventEvent(event);
  2988. let $isCollect = $collectBtn.querySelector(".collect");
  2989. let $unCollect = $collectBtn.querySelector(".uncollect");
  2990. let folderInfo = await CSDNFavoriteApi.folderListWithCheck(
  2991. window.location.origin + window.location.pathname
  2992. );
  2993. if (!folderInfo) {
  2994. return;
  2995. }
  2996. let isFavoriteFolderIdList = [];
  2997. folderInfo.forEach((item) => {
  2998. if (item.IsFavorite) {
  2999. isFavoriteFolderIdList.push(item.ID);
  3000. }
  3001. });
  3002. let createCollectItem = (data) => {
  3003. let folderId = data.ID;
  3004. let $item = domutils.createElement(
  3005. "li",
  3006. {
  3007. className: "csdn-collection-item",
  3008. innerHTML: (
  3009. /*html*/
  3010. `
  3011. <div class="csdn-collection-item_left">
  3012. <div class="csdn-collection-item_title">
  3013. <span class="title-m">${data.Name}</span>
  3014. </div>
  3015. <span class="csdn-collection-item_ext">
  3016. <span class="csdn-collection-item_length">${data.FavoriteNum}条内容</span>
  3017. <span class="dot">・</span>
  3018. <span class="csdn-collection-controls">${data.IsPrivate ? "私密" : "公开"}</span>
  3019. </span>
  3020. </div>
  3021. <span class="collect-btn">${data.IsFavorite ? "已收藏" : "收藏"}</span>
  3022. `
  3023. )
  3024. },
  3025. {
  3026. "data-is-collect": data.IsFavorite
  3027. }
  3028. );
  3029. $item.querySelector(".title-m");
  3030. let $contentLength = $item.querySelector(
  3031. ".csdn-collection-item_length"
  3032. );
  3033. $item.querySelector(
  3034. ".csdn-collection-controls"
  3035. );
  3036. let $collectBtn2 = $item.querySelector(".collect-btn");
  3037. domutils.on($collectBtn2, "click", async (event2) => {
  3038. let articleDetailUrl = _unsafeWindow.articleDetailUrl;
  3039. if (articleDetailUrl == null) {
  3040. articleDetailUrl = window.location.origin + window.location.pathname;
  3041. }
  3042. let articleId = _unsafeWindow.articleId;
  3043. if (articleId == null) {
  3044. log.error("获取文章ID失败");
  3045. Qmsg.error("获取文章ID失败");
  3046. return;
  3047. }
  3048. let username = _unsafeWindow.username;
  3049. if (username == null) {
  3050. log.error("获取文章作者失败");
  3051. Qmsg.error("获取文章作者失败");
  3052. return;
  3053. }
  3054. let articleTitle = _unsafeWindow.articleTitle;
  3055. if (articleTitle == null) {
  3056. articleTitle = document.title.replace(/-CSDN博客$/, "");
  3057. }
  3058. if (articleTitle == null) {
  3059. log.error("获取文章标题失败");
  3060. Qmsg.error("获取文章标题失败");
  3061. return;
  3062. }
  3063. let articleDesc = _unsafeWindow.articleDesc;
  3064. if (articleDesc == null) {
  3065. let $meta = $("meta[name='description']");
  3066. if ($meta) {
  3067. articleDesc = $meta.getAttribute("content");
  3068. }
  3069. }
  3070. if (articleDesc == null) {
  3071. log.error("获取文章描述失败");
  3072. Qmsg.error("获取文章描述失败");
  3073. return;
  3074. }
  3075. let folderIdList = [...isFavoriteFolderIdList];
  3076. let $loading = Qmsg.loading("处理中...");
  3077. try {
  3078. let checkResponse = await CSDNFavoriteApi.checkFavoriteByUrl(
  3079. articleDetailUrl
  3080. );
  3081. if (checkResponse == null) {
  3082. return;
  3083. }
  3084. log.info(folderId, checkResponse);
  3085. let toCollect = !checkResponse[folderId];
  3086. if (toCollect) {
  3087. log.info(`添加收藏`);
  3088. folderIdList.push(folderId);
  3089. } else {
  3090. log.info(`取消收藏`);
  3091. folderIdList.splice(folderIdList.indexOf(folderId), 1);
  3092. }
  3093. let response = await CSDNFavoriteApi.addFavoriteInFolds({
  3094. author: username,
  3095. url: articleDetailUrl,
  3096. source: "blog",
  3097. sourceId: articleId,
  3098. title: articleTitle,
  3099. description: articleDesc,
  3100. fromType: "PC",
  3101. username: data.Username,
  3102. folderIdList
  3103. });
  3104. if (!response) {
  3105. return;
  3106. }
  3107. let check_isCollect = await CSDNFavoriteApi.checkFavoriteByUrl(articleDetailUrl);
  3108. if (check_isCollect == null) {
  3109. return;
  3110. }
  3111. log.info(folderId, check_isCollect);
  3112. $item.setAttribute(
  3113. "data-is-collect",
  3114. (!!check_isCollect[folderId]).toString()
  3115. );
  3116. if (toCollect) {
  3117. if (!check_isCollect[folderId]) {
  3118. log.error("收藏失败", check_isCollect, folderId);
  3119. Qmsg.error("收藏失败");
  3120. } else {
  3121. log.success("收藏成功");
  3122. Qmsg.success("收藏成功");
  3123. domutils.text($collectBtn2, "已收藏");
  3124. if (!isFavoriteFolderIdList.includes(folderId)) {
  3125. isFavoriteFolderIdList.push(folderId);
  3126. }
  3127. data.FavoriteNum++;
  3128. }
  3129. } else {
  3130. if (!check_isCollect[folderId]) {
  3131. log.success("取消收藏成功");
  3132. Qmsg.success("取消收藏成功");
  3133. domutils.text($collectBtn2, "收藏");
  3134. if (isFavoriteFolderIdList.includes(folderId)) {
  3135. isFavoriteFolderIdList.splice(
  3136. isFavoriteFolderIdList.indexOf(folderId),
  3137. 1
  3138. );
  3139. }
  3140. data.FavoriteNum--;
  3141. } else {
  3142. log.error("取消收藏失败", check_isCollect, folderId);
  3143. Qmsg.error("取消收藏失败");
  3144. }
  3145. }
  3146. domutils.text($contentLength, `${data.FavoriteNum}条内容`);
  3147. let findValue = Object.values(check_isCollect).find(
  3148. (item) => item
  3149. );
  3150. if (findValue) {
  3151. domutils.show($isCollect, false);
  3152. domutils.hide($unCollect, false);
  3153. } else {
  3154. domutils.show($unCollect, false);
  3155. domutils.hide($isCollect, false);
  3156. }
  3157. } catch (error) {
  3158. log.error(error);
  3159. } finally {
  3160. $loading.close();
  3161. }
  3162. });
  3163. return $item;
  3164. };
  3165. let $alert = __pops.alert({
  3166. title: {
  3167. text: "添加收藏夹",
  3168. position: "center"
  3169. },
  3170. content: {
  3171. text: (
  3172. /*html*/
  3173. `
  3174. <ul class="csdn-collection-items"></ul>
  3175. `
  3176. ),
  3177. html: true
  3178. },
  3179. btn: {
  3180. ok: {
  3181. enable: false
  3182. }
  3183. },
  3184. width: PanelUISize.setting.width,
  3185. height: PanelUISize.setting.height,
  3186. drag: true,
  3187. mask: {
  3188. enable: true
  3189. },
  3190. style: (
  3191. /*css*/
  3192. `
  3193. .csdn-collection-items{
  3194. --font-size: 16px;
  3195. }
  3196. .csdn-collection-items{
  3197. font-size: var(--font-size);
  3198. font-weight: 400;
  3199. padding: 0 20px 0;
  3200. margin: 24px 0;
  3201. overflow: auto;
  3202. -ms-scroll-chaining: none;
  3203. overscroll-behavior: contain;
  3204. }
  3205. .csdn-collection-item{
  3206. width: 100%;
  3207. height: 62px;
  3208. line-height: normal;
  3209. position: relative;
  3210. padding: 8px 12px;
  3211. cursor: pointer;
  3212. display: -webkit-box;
  3213. display: -ms-flexbox;
  3214. display: flex;
  3215. -webkit-box-align: center;
  3216. -ms-flex-align: center;
  3217. align-items: center;
  3218. -webkit-box-pack: justify;
  3219. -ms-flex-pack: justify;
  3220. justify-content: space-between;
  3221. border-bottom: 1px solid #f0f0f5;
  3222. }
  3223. .csdn-collection-item_left{
  3224. line-height: normal;
  3225. flex: 1;
  3226. overflow: hidden;
  3227. }
  3228. .csdn-collection-item_title{
  3229. overflow: hidden;
  3230. text-overflow: ellipsis;
  3231. white-space: nowrap;
  3232. width: 100%;
  3233. }
  3234. .csdn-collection-item_ext{
  3235. font-weight: 400;
  3236. color: #999aaa;
  3237. line-height: 17px;
  3238. margin-top: 8px;
  3239. font-size: .8em;
  3240. overflow: hidden;
  3241. text-overflow: ellipsis;
  3242. white-space: nowrap;
  3243. width: 100%;
  3244. display: inline-flex;
  3245. align-items: center;
  3246. }
  3247. .collect-btn{
  3248. color: #555666;
  3249. font-size: var(--font-size);
  3250. width: 64px;
  3251. height: 30px;
  3252. line-height: 30px;
  3253. border-radius: 20px;
  3254. text-align: center;
  3255. -webkit-transition: all .2s;
  3256. transition: all .2s;
  3257. border: 1px solid #ccccd8;
  3258. }
  3259. .csdn-collection-item[data-is-collect="true"] .collect-btn{
  3260. color: #999aaa;
  3261. background: rgba(232, 232, 237, .3);
  3262. border: 1px solid #e8e8ed;
  3263. }
  3264. /* .csdn-collection-item:hover{
  3265. background: #f5f6f7;
  3266. }
  3267. .csdn-collection-item:hover .collect-btn{
  3268. border: 1px solid #555666;
  3269. } */
  3270. `
  3271. )
  3272. });
  3273. let $collectionContainer = $alert.$shadowRoot.querySelector(
  3274. ".csdn-collection-items"
  3275. );
  3276. folderInfo.forEach((folderInfoItem) => {
  3277. let $item = createCollectItem(folderInfoItem);
  3278. $collectionContainer.appendChild($item);
  3279. });
  3280. },
  3281. { capture: true }
  3282. );
  3283. });
  3284. }
  3285. };
  3286. const ShieldCSS = "/* 右下角的买一年送3个月的广告图标 */\r\n.blind_box {\r\n display: none !important;\r\n}\r\n";
  3287. const M_CSDNWenKu = {
  3288. init() {
  3289. addStyle(ShieldCSS);
  3290. PopsPanel.execMenu("m-csdn-wenku-shieldBottomToolbar", () => {
  3291. this.shieldBottomToolbar();
  3292. });
  3293. },
  3294. /**
  3295. * 【屏蔽】底部工具栏
  3296. */
  3297. shieldBottomToolbar() {
  3298. log.info("【屏蔽】底部工具栏");
  3299. CommonUtil.addBlockCSS(`.page-container > div.btn`);
  3300. }
  3301. };
  3302. const CSDNBlockCSS = "/* 右下角悬浮图标 买1年送3个月 */\r\n.page-container .blind_box,\r\n/* 底部工具栏右边的 开会员按钮(低至xx元/次) */\r\n.page-container .btn .ml-12,\r\n/* 登录弹窗 */\r\n.passport-login-container,\r\n/* 通用广告className匹配 */\r\n.ads {\r\n display: none !important;\r\n}\r\n";
  3303. const M_CSDNDownload = {
  3304. init() {
  3305. PopsPanel.execMenuOnce("m-csdn-download-removeAds", () => {
  3306. return addStyle(CSDNBlockCSS);
  3307. });
  3308. PopsPanel.execMenuOnce(
  3309. "m-csdn-download-automaticallyExpandResourceIntroduction",
  3310. () => {
  3311. return this.automaticallyExpandResourceIntroduction();
  3312. }
  3313. );
  3314. },
  3315. /**
  3316. * 自动展开资源介绍
  3317. */
  3318. automaticallyExpandResourceIntroduction() {
  3319. log.info("自动展开资源介绍");
  3320. return [
  3321. CommonUtil.addBlockCSS("label.unfold-font"),
  3322. addStyle(
  3323. /*css*/
  3324. `
  3325. .resource-desc{
  3326. max-height: unset !important;
  3327. overflow: unset !important;
  3328. }
  3329. `
  3330. )
  3331. ];
  3332. }
  3333. };
  3334. const M_CSDN = {
  3335. init() {
  3336. if (CSDNRouter.isLink()) {
  3337. log.info("Router: 中转链接");
  3338. M_CSDNLink.init();
  3339. } else if (CSDNRouter.isHuaWeiCloudBlog()) {
  3340. log.info("Router: 华为云联盟");
  3341. M_CSDNHuaWeiCloud.init();
  3342. } else if (CSDNRouter.isBlog()) {
  3343. log.info("Router: 博客");
  3344. M_CSDNBlog.init();
  3345. } else if (CSDNRouter.isWenKu()) {
  3346. log.info("Router: 文库");
  3347. M_CSDNWenKu.init();
  3348. } else if (CSDNRouter.isDownload()) {
  3349. log.info("Router: 资源下载");
  3350. M_CSDNDownload.init();
  3351. } else {
  3352. log.error("暂未适配,请反馈开发者:" + globalThis.location.href);
  3353. }
  3354. }
  3355. };
  3356. PopsPanel.init();
  3357. let isMobile = utils.isPhone();
  3358. let CHANGE_ENV_SET_KEY = "change_env_set";
  3359. let chooseMode = _GM_getValue(CHANGE_ENV_SET_KEY);
  3360. GM_Menu.add({
  3361. key: CHANGE_ENV_SET_KEY,
  3362. text: `⚙ 自动: ${isMobile ? "移动端" : "PC端"}`,
  3363. autoReload: false,
  3364. isStoreValue: false,
  3365. showText(text) {
  3366. if (chooseMode == null) {
  3367. return text;
  3368. }
  3369. return text + ` 手动: ${chooseMode == 1 ? "移动端" : chooseMode == 2 ? "PC端" : "未知"}`;
  3370. },
  3371. callback: () => {
  3372. let allowValue = [0, 1, 2];
  3373. let chooseText = window.prompt(
  3374. "请输入当前脚本环境判定\n\n自动判断: 0\n移动端: 1\nPC端: 2",
  3375. "0"
  3376. );
  3377. if (!chooseText) {
  3378. return;
  3379. }
  3380. let chooseMode2 = parseInt(chooseText);
  3381. if (isNaN(chooseMode2)) {
  3382. Qmsg.error("输入的不是规范的数字");
  3383. return;
  3384. }
  3385. if (!allowValue.includes(chooseMode2)) {
  3386. Qmsg.error("输入的值必须是0或1或2");
  3387. return;
  3388. }
  3389. if (chooseMode2 == 0) {
  3390. _GM_deleteValue(CHANGE_ENV_SET_KEY);
  3391. } else {
  3392. _GM_setValue(CHANGE_ENV_SET_KEY, chooseMode2);
  3393. }
  3394. }
  3395. });
  3396. if (chooseMode != null) {
  3397. log.info(`手动判定为${chooseMode === 1 ? "移动端" : "PC端"}`);
  3398. if (chooseMode == 1) {
  3399. M_CSDN.init();
  3400. } else if (chooseMode == 2) {
  3401. CSDN.init();
  3402. } else {
  3403. Qmsg.error("意外,手动判定的值不在范围内");
  3404. _GM_deleteValue(CHANGE_ENV_SET_KEY);
  3405. }
  3406. } else {
  3407. if (isMobile) {
  3408. log.info("自动判定为移动端");
  3409. M_CSDN.init();
  3410. } else {
  3411. log.info("自动判定为PC端");
  3412. CSDN.init();
  3413. }
  3414. }
  3415.  
  3416. })(Qmsg, DOMUtils, Utils, pops);