掘金沸点过滤器

过滤掉那些看起来很睿智的沸点和伙计

  1. // ==UserScript==
  2. // @name 掘金沸点过滤器
  3. // @version 0.2.5
  4. // @description 过滤掉那些看起来很睿智的沸点和伙计
  5. // @author 睿智的河水
  6. // @match *://juejin.im/*
  7. // @namespace https://gf.qytechs.cn/scripts/388549
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict'
  13.  
  14. const jjStyle = key => {
  15. if (key.substring(0, 1) === 'V') {
  16. key = `v-${key.substring(1)}`
  17. }
  18. return `
  19. .jj-block-dialog {
  20. position: fixed;
  21. z-index: 9999;
  22. top: 0;
  23. left: 0;
  24. width: 100%;
  25. height: 100%;
  26. background: rgba(0,0,0,.25);
  27. }
  28. .jj-block-dialog-box {
  29. position: relative;
  30. width: 520px;
  31. background: #fff;
  32. padding: 20px;
  33. margin: 8% auto 0;
  34. border-radius: 5px;
  35. }
  36. .jj-block-dialog-box .close {
  37. position: absolute;
  38. right: -15px;
  39. top: -15px;
  40. width: 26px;
  41. height: 26px;
  42. font-size: 26px;
  43. text-align: center;
  44. line-height: 26px;
  45. color: #666;
  46. background: #fff;
  47. border-radius: 50%;
  48. border: 1px solid #ccc;
  49. transform: rotateZ(45deg);
  50. cursor: pointer;
  51. user-select: none;
  52. }
  53. .jj-block-dialog-box .label {
  54. font-size: 14px;
  55. }
  56. .jj-block-dialog-box .textarea {
  57. height: 80px;
  58. margin: 12px 0;
  59. padding: 6px;
  60. color: #333;
  61. }
  62. .jj-block-dialog-box .textarea:focus {
  63. border-color: #007fff;
  64. }
  65. .jj-block-dialog-box .button {
  66. width: 80px;
  67. }
  68. .jj-block-dialog-box .tip {
  69. color: #888;
  70. margin-left: 12px;
  71. }
  72. .block-action[data-${key}] .action-title-box[data-${key}] {
  73. flex: 1;
  74. height: 100%;
  75. font-size: 13px;
  76. color: #8a93a0;
  77. }
  78. .block-panel[data-${key}] {
  79. position: absolute;
  80. top: 100%;
  81. left: 50%;
  82. margin: 0 0 0 -5.5rem;
  83. width: 11rem;
  84. background-color: #fff;
  85. border: 1px solid #ebebeb;
  86. border-radius: 2px;
  87. z-index: 101;
  88. }
  89. .block-panel[data-${key}]:after,
  90. .block-panel[data-${key}]:before {
  91. content: '';
  92. position: absolute;
  93. top: 0;
  94. left: 50%;
  95. }
  96. .block-panel[data-${key}]:before {
  97. margin: -7px 0 0 -7px;
  98. border: 7px solid transparent;
  99. border-top: none;
  100. border-bottom: 7px solid #ebebeb;
  101. }
  102. .block-panel[data-${key}]:after {
  103. margin: -6px 0 0 -6px;
  104. border: 6px solid transparent;
  105. border-top: none;
  106. border-bottom: 6px solid #fff;
  107. }
  108. .block-panel[data-${key}] .block-item[data-${key}] {
  109. font-size: 13px;
  110. color: #8a93a0;
  111. text-align: center;
  112. padding: 0.5rem 0.9rem;
  113. }
  114. .block-panel[data-${key}] .block-item[data-${key}]:not(:last-child) {
  115. border-bottom: 1px solid #ebebeb;
  116. }
  117. .block-panel[data-${key}] .block-item[data-${key}]:hover {
  118. background-color: #fdfdfd;
  119. }
  120. `
  121. }
  122.  
  123. /**
  124. * 拿到vue
  125. */
  126. const JJ = document.querySelector('#juejin').__vue__
  127.  
  128. /**
  129. * 清除空值
  130. */
  131. const cleanArray = arr => {
  132. if (Array.isArray(arr)) {
  133. return arr.filter(v => v && v.trim())
  134. }
  135. return arr
  136. }
  137.  
  138. /**
  139. * 获取缓存数据
  140. */
  141. const getLocal = key => {
  142. return cleanArray(JSON.parse(localStorage.getItem(key)))
  143. }
  144.  
  145. /**
  146. * 设置缓存数据
  147. */
  148. const setLocal = (key, val) => {
  149. return localStorage.setItem(key, JSON.stringify(val))
  150. }
  151.  
  152. /**
  153. * 过滤列表数据
  154. */
  155. const filterList = () => {
  156. const pinItem = document.querySelectorAll('.pin')
  157. let blockList = getLocal('BLOCK_LIST') || []
  158. let blockUser = getLocal('BLOCK_USER') || []
  159.  
  160. // 遍历当前沸点列表
  161. for (const v of Array.from(pinItem)) {
  162. const vInfo = v.__vue__.pin
  163.  
  164. if (
  165. blockList.includes(vInfo.id) ||
  166. blockUser.includes(vInfo.user.id)
  167. ) {
  168. v.classList.add('hidden')
  169. continue
  170. }
  171.  
  172. v.classList.remove('hidden')
  173.  
  174. const action = v.querySelector('.action-box')
  175.  
  176. // 注入屏蔽代码
  177. if (action && !action.classList.contains('is-append')) {
  178. const blockEl = document.createElement('div')
  179. const bKey = Object.keys(action.firstElementChild.dataset)[0]
  180. blockEl.dataset[bKey] = ''
  181. blockEl.classList = 'block-action action'
  182. action.appendChild(blockEl)
  183.  
  184. const blockTitle = document.createElement('div')
  185. blockTitle.textContent = '✞ 屏蔽'
  186. blockTitle.dataset[bKey] = ''
  187. blockTitle.classList = 'action-title-box'
  188. blockEl.appendChild(blockTitle)
  189.  
  190. const blockPanel = document.createElement('div')
  191. blockPanel.dataset[bKey] = ''
  192. blockPanel.classList = 'block-panel shadow hidden'
  193. blockEl.appendChild(blockPanel)
  194.  
  195. blockTitle.onclick = () => {
  196. blockPanel.classList.toggle('hidden')
  197. }
  198.  
  199. const addElement = (label, cb) => {
  200. const el = document.createElement('div')
  201. el.textContent = label
  202. el.dataset[bKey] = ''
  203. el.classList = 'block-item'
  204. el.onclick = cb
  205. blockPanel.appendChild(el)
  206. }
  207.  
  208. addElement('屏蔽此条', () => {
  209. blockList.push(vInfo.id)
  210. setLocal('BLOCK_LIST', blockList)
  211. v.classList.add('hidden')
  212. })
  213. addElement('屏蔽此人', () => {
  214. blockUser.push(vInfo.user.user_id)
  215. setLocal('BLOCK_USER', blockUser)
  216. v.classList.add('hidden')
  217. filterList()
  218. })
  219. addElement('查看已屏蔽', () => {
  220. blockList = getLocal('BLOCK_LIST') || []
  221. blockUser = getLocal('BLOCK_USER') || []
  222. let dialog = document.querySelector('.jj-block-dialog')
  223. if (dialog) {
  224. document.body.removeChild(dialog)
  225. }
  226. dialog = document.createElement('div')
  227. dialog.classList = 'jj-block-dialog'
  228. dialog.innerHTML = `
  229. <div class="jj-block-dialog-box">
  230. <span id="jj-block-close" class="close">+</span>
  231. <label class="label">已屏蔽的沸点</label>
  232. <textarea id="jj-block-list" class="textarea">${blockList.join(',')}</textarea>
  233. <label class="label">已屏蔽的用户</label>
  234. <textarea id="jj-block-user" class="textarea">${blockUser.join(',')}</textarea>
  235. <button id="jj-block-update" class="button">更新</button>
  236. <span class="tip">多条数据用逗号(,)隔开,留空则不屏蔽任何沸点和用户</span>
  237. </div>
  238. `
  239. document.body.append(dialog)
  240. const _ = el => document.querySelector(el) || null
  241. _('#jj-block-close').onclick = () => {
  242. document.body.removeChild(dialog)
  243. }
  244. _('#jj-block-update').onclick = () => {
  245. const blockList = _('#jj-block-list').value.split(',')
  246. const blockUser = _('#jj-block-user').value.split(',')
  247. setLocal('BLOCK_LIST', blockList)
  248. setLocal('BLOCK_USER', blockUser)
  249. document.body.removeChild(dialog)
  250. filterList()
  251. JJ.$alertMsg('屏蔽列表已更新')
  252. }
  253. })
  254.  
  255. if (!document.getElementById('jj-style')) {
  256. const style = document.createElement('style')
  257. style.textContent = jjStyle(bKey)
  258. style.id = 'jj-style'
  259. document.head.append(style)
  260. }
  261.  
  262. action.classList.add('is-append')
  263. }
  264. }
  265. }
  266.  
  267. /**
  268. * 监听并过滤
  269. */
  270. const watchPin = () => {
  271. const target = document.querySelector('.pin-list-view, .pin-content')
  272. const config = { childList: true, subtree: true }
  273. const observer = new MutationObserver(() => {
  274. filterList()
  275. })
  276.  
  277. if (target) {
  278. observer.observe(target, config)
  279. }
  280. }
  281. JJ.$router.afterEach(() => {
  282. watchPin()
  283. })
  284. watchPin()
  285. })()

QingJ © 2025

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