番茄小说阅读辅助器

可以下载番茄小说内容,记录阅读位置(滚动位置),可以自动滚动,快捷书签,好用!

安裝腳本?
作者推薦腳本

您可能也會喜歡 unicode1

安裝腳本
  1. // ==UserScript==
  2. // @name 番茄小说阅读辅助器
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.601
  5. // @description 可以下载番茄小说内容,记录阅读位置(滚动位置),可以自动滚动,快捷书签,好用!
  6. // @author twjx
  7. // @match *://fanqienovel.com/*
  8. // @require https://cdn.jsdelivr.net/npm/lil-gui@0.16
  9. // @require https://update.gf.qytechs.cn/scripts/522780/1518758/dialog-gui.js
  10. // @require https://update.gf.qytechs.cn/scripts/521360/1523656/unicode1.js
  11. // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
  12. // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
  13. // @license GNU AGPLv3
  14. // @resource swalStyle https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.css
  15. // @icon data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE4Ljg3MjcgMEg1LjEyNzI3QzIuMjkwOTEgMCAwIDIuMjkwOTEgMCA1LjEyNzI3VjE4Ljg3MjdDMCAyMS43MDkxIDIuMjkwOTEgMjQgNS4xMjcyNyAyNEgxOC44NzI3QzIxLjcwOTEgMjQgMjQgMjEuNzA5MSAyNCAxOC44NzI3VjUuMTI3MjdDMjQgMi4yOTA5MSAyMS43MDkxIDAgMTguODcyNyAwWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjEyNzI3IDBIMTguODcyN0MyMS43MDkxIDAgMjQgMi4yOTA5MSAyNCA1LjEyNzI3VjE4Ljg3MjdDMjQgMjEuNzA5MSAyMS43MDkxIDI0IDE4Ljg3MjcgMjRINS4xMjcyN0MyLjI5MDkxIDI0IDAgMjEuNzA5MSAwIDE4Ljg3MjdWNS4xMjcyN0MwIDIuMjkwOTEgMi4yOTA5MSAwIDUuMTI3MjcgMFpNMjMuNDc1NyA1LjEyNzI3QzIzLjQ3NTcgMi41OTYzNiAyMS40MDMgMC41MjM2MzYgMTguODcyIDAuNTIzNjM2SDUuMTI2NTlDMi41OTU2OCAwLjUyMzYzNiAwLjUyMjk0OSAyLjU5NjM2IDAuNTIyOTQ5IDUuMTI3MjdWMTguODcyN0MwLjUyMjk0OSAyMS40MDM2IDIuNTk1NjggMjMuNDc2NCA1LjEyNjU5IDIzLjQ3NjRIMTguODcyQzIxLjQwMyAyMy40NzY0IDIzLjQ3NTcgMjEuNDAzNiAyMy40NzU3IDE4Ljg3MjdWNS4xMjcyN1oiIGZpbGw9IiNFNkU2RTYiLz4KPHBhdGggZD0iTTE1LjA3NjIgMFY1LjA0TDE3LjAxOCAzLjkyNzI3TDE4Ljk1OTggNS4wNFYwSDE1LjA3NjJaIiBmaWxsPSIjRUU1NTI4Ii8+CjxwYXRoIGQ9Ik0yNCAxMy45NjM2QzIxLjI1MDkgMTAuNjkwOCAxNi45MDkxIDguNTc0NDYgMTIuMDIxOCA4LjU3NDQ2QzcuMDkwOTEgOC41NzQ0NiAyLjcyNzI3IDEwLjcxMjYgMCAxNC4wMjlWMTguODcyNkMwIDIxLjcwOSAyLjI5MDkxIDIzLjk5OTkgNS4xMjcyNyAyMy45OTk5SDE4Ljg3MjdDMjEuNzA5MSAyMy45OTk5IDI0IDIxLjcwOSAyNCAxOC44NzI2VjEzLjk2MzZaIiBmaWxsPSJ1cmwoI3BhaW50MF9yYWRpYWxfNjA3XzEyNTA1KSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyLjc4NTYgMTMuODk4MkMxMi43NjM4IDEzLjAwMzcgMTIuNDE0NyAxMi41ODkxIDEyLjAwMDIgMTIuNTg5MUMxMS41NjM4IDEyLjYxMDkgMTEuMjM2NSAxMy4wMjU1IDExLjI1ODQgMTMuODk4MkMxMS4yNTg0IDE0LjgxNDYgMTIuMDQzOCAxNS44NjE4IDEyLjA0MzggMTUuODYxOEMxMi4wNDM4IDE1Ljg2MTggMTIuNzg1NiAxNC44MTQ2IDEyLjc4NTYgMTMuODk4MlpNNi4zNDk0NiAxOC42NzYzQzcuMjY1ODMgMTguNjc2MyA4LjMxMzEgMTkuNDE4MSA4LjMxMzEgMTkuNDE4MUM4LjMxMzEgMTkuNDE4MSA3LjI2NTgzIDIwLjIwMzUgNi4zNDk0NiAyMC4yMDM1QzUuNDMzMSAyMC4yMDM1IDUuMDE4NTUgMTkuODc2MyA1LjAxODU1IDE5LjQzOTlDNS4wNDAzNyAxOS4wNDcyIDUuNDU0OTIgMTguNjk4MSA2LjM0OTQ2IDE4LjY3NjNaTTE4Ljk2MSAxOS40NjE5QzE4Ljk2MSAxOS44NzY0IDE4LjU0NjUgMjAuMjI1NSAxNy42MzAxIDIwLjIyNTVDMTYuNzEzOCAyMC4yMjU1IDE1LjY2NjUgMTkuNDQwMSAxNS42NjY1IDE5LjQ0MDFDMTUuNjY2NSAxOS40NDAxIDE2LjczNTYgMTguNjc2NCAxNy42MzAxIDE4LjY5ODJDMTguNTQ2NSAxOC42OTgyIDE4Ljk2MSAxOS4wMjU1IDE4Ljk2MSAxOS40NjE5Wk0xNy4zMDIyIDE0Ljg1ODFDMTcuNjA3NiAxNS4xNjM1IDE3LjU0MjIgMTUuNjg3MiAxNi44ODc2IDE2LjM0MTdDMTYuMjMzMSAxNi45NzQ1IDE0Ljk0NTggMTcuMTcwOCAxNC45NDU4IDE3LjE3MDhDMTQuOTQ1OCAxNy4xNzA4IDE1LjE2NCAxNS44ODM1IDE1LjgxODUgMTUuMjUwOEMxNi40NzMxIDE0LjU5NjMgMTcuMDE4NSAxNC41NTI2IDE3LjMwMjIgMTQuODU4MVpNOS4wNTU2NCAxNy4xNDkyQzkuMDU1NjQgMTcuMTQ5MiA4LjgzNzQ2IDE1Ljg2MiA4LjE4MjkxIDE1LjIyOTJDNy41MjgzNiAxNC41OTY1IDYuOTgyOTEgMTQuNTUyOSA2LjY5OTI3IDE0LjgzNjVDNi40MTU2NCAxNS4xNDIgNi40NTkyNyAxNS42ODc0IDcuMTEzODIgMTYuMzIwMUM3Ljc2ODM2IDE2Ljk1MjkgOS4wNTU2NCAxNy4xNDkyIDkuMDU1NjQgMTcuMTQ5MloiIGZpbGw9IndoaXRlIi8+CjxkZWZzPgo8cmFkaWFsR3JhZGllbnQgaWQ9InBhaW50MF9yYWRpYWxfNjA3XzEyNTA1IiBjeD0iMCIgY3k9IjAiIHI9IjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLjA5ODkgMjQuMjEyKSBzY2FsZSgxNC41OTg0IDkuMzgyNzcpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0NDMDUwMCIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRjVGMDAiLz4KPC9yYWRpYWxHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K
  16. // @grant GM_download
  17. // @grant GM_xmlhttpRequest
  18. // @connect p9-reading-sign.fqnovelpic.com
  19. // @connect p3-reading-sign.fqnovelpic.com
  20. // ==/UserScript==
  21.  
  22. (function() {
  23. 'use strict';
  24. //unsafeWindow
  25. window.data='';
  26. window.num=0;
  27. window.alldata=[];
  28. window.movep=[];
  29. window.img=[];
  30. window.thedata={};
  31. window.sleep=async function(ms){
  32. return new Promise(resolve => setTimeout(resolve, ms));
  33. };
  34. window.unicode_data();
  35. window.downloader={
  36. newxml:function(url,idata,num,num1,aa) {
  37. const xhr = new XMLHttpRequest();
  38. xhr.open('GET',url);
  39. xhr.overrideMimeType('text/plain; charset=utf-8');
  40. xhr.onload = function () {
  41. if (xhr.status === 200) {
  42. let parser = new DOMParser();
  43. var doc = parser.parseFromString(xhr.responseText, 'text/html')
  44. var content='' /* 排除图片的元素*/
  45. Array.from(doc.querySelector('.muye-reader-content div').children,).filter(e=>!e.children.length).forEach(x=>{
  46. content+=downloader.decode(x.innerText+'\n')//加换行
  47. })
  48. idata.data.push({
  49. chapter:doc.querySelector('.muye-reader-box-header').children[0].innerText,
  50. chapter1:num1,
  51. chapter2:num,
  52. word_count:doc.querySelector('.muye-reader-box-header').children[1]==undefined ? undefined : doc.querySelector('.muye-reader-box-header').children[1].children[0].innerText.split(':')[1],
  53. updated_at:doc.querySelector('.muye-reader-box-header').children[1]==undefined ? undefined : doc.querySelector('.muye-reader-box-header').children[1].children[1].innerText.split(':')[1],
  54. data:content,
  55. })
  56. downloader.find_img(doc) == false ? (()=>{})() : (()=>{
  57. img.push(downloader.find_img(doc))
  58. })()
  59. console.log(aa+' 机改1:'+num1+' 机改2:'+num+'下载完成')
  60. }
  61. };
  62. xhr.send();
  63. },
  64. decode:function(content) {
  65. var newdata = '';
  66. for (let x of content) {
  67. if (String(x).charCodeAt(0) in unicode_data == true) {
  68. newdata += unicode_data[String(x).charCodeAt(0)];
  69. } else {
  70. newdata += String(x);
  71. }
  72. }
  73. return newdata;
  74. },
  75. dispose:async function(children,type){
  76. var jdata=children.children[0].innerHTML.split('<span class="volume-dot"></span>')
  77. var num=1
  78. alldata.push({
  79. name:jdata[0],
  80. volume:jdata[0],
  81. allchapter:jdata[1],
  82. data:[]})
  83. console.log('卷创建完毕')
  84. for(let x of children.children[1].children){
  85. this.newxml(x.children[0].href,alldata[alldata.length-1],num,num1,x.innerText.split(' ')[0])
  86. num+=1
  87. num1+=1
  88. await sleep(Number(document.querySelectorAll('.widget')[2].children[0].value))//50毫秒一下最好不要,卡爆
  89. }
  90. },
  91. find_img:function(doc){
  92. var a=Array.from(doc.querySelector('.muye-reader-content').children[0].children,).filter(e=>e.children[0])
  93. return a.length == 0 ? false : (()=>{
  94. var b=[]
  95. a.forEach(e=>{
  96. b.push({
  97. src:e.children[0].src || e.children[0].children[0].src,//防止扉页 版权 等类似格式不同引发的错误
  98. name:this.decode(e.children[1]==true ? e.children.innerText : doc.querySelector('.muye-reader-box-header').children[0].innerText),//忘了还要解码
  99. chapter:doc.querySelector('.muye-reader-box-header').children[0].innerText,
  100. render:{
  101. width:e.children[0].width || e.children[0].children[0].width,
  102. height:e.children[0].height || e.children[0].children[0].height,
  103. },
  104. original:{
  105. width:e.children[0].naturalWidth==undefined ? e.children[0].children[0].naturalWidth : e.children[0].naturalWidth,
  106. height:e.children[0].naturalHeight==undefined ? e.children[0].children[0].naturalHeight : e.children[0].naturalHeight,
  107. },
  108. })
  109. })
  110. return b
  111. })()
  112. },
  113. download:function(name, text,type) {
  114. if(type=='text'){
  115. GM_download({
  116. url: 'data:text/plain;charset=utf-8,' + encodeURIComponent(text),
  117. name: name + '.txt',
  118. saveAs: true,
  119. onload: function(){
  120. console.log('下载完成')
  121. }
  122. });
  123. }
  124. },
  125. downloadd:async function(type){
  126. data=''
  127. console.log('正在排序...')
  128. window.d=0
  129. for(let x=0;x<alldata.length;x++){
  130. data+=alldata[x].name+' '+alldata[x].allchapter+'\n'
  131. for(let x1=0;x1<alldata[x].data.length;x1++){
  132. d+=1
  133. for(let x2 of alldata[x].data){
  134. if(x2.chapter1==d){
  135. data+='\n'+x2.chapter.includes('章') == true ? '第'+[x2.chapter,x2.chapter1,x2.chapter2][type]+'章'+x2.chapter.split('章')[1] : (()=>{return type == 0 ?x2.chapter: '第'+[x2.chapter,x2.chapter1,x2.chapter2][type]+'章 '})()+x2.chapter+(x2.word_count==undefined ? '' : `\n字数:${x2.word_count} 更新日期:${x2.updated_at}\n`)+x2.data
  136. }
  137. }
  138. }
  139. }
  140. this.download(
  141. unsafeWindow.__INITIAL_STATE__.page.bookName,
  142. unsafeWindow.__INITIAL_STATE__.page.bookName+
  143. '作者:'+unsafeWindow.__INITIAL_STATE__.page.author+
  144. '\n字数'+document.querySelector('.info-count-word').innerText.replace('\n','')+
  145. "\n此文件由番茄小说阅读辅助器下载https://gf.qytechs.cn/zh-CN/scripts/521377-番茄小说阅读辅助器\n请支持正版番茄小说"
  146. +'\n'+data,'text')
  147. await sleep(1000)
  148. data=''
  149. alldata=[]
  150. if(await confirm('是否下载图片')==true){
  151. this.loadimg=new this.downloadimg()
  152. this.loadimg.loadimg(img.flat(Infinity))
  153. }
  154. },
  155. loadrecord:function(){
  156. document.querySelectorAll('.chapter-item').forEach((x)=>{
  157. var recorddata=thedata.read.read_record.filter(e=>e.chapterid==x.children[0].href.split('/')[4])
  158. if(recorddata.length==1){
  159. x.innerHTML+='<span class="tooltip">已看'+Math.round(((recorddata[0].scrolltop+window.innerHeight)/recorddata[0].scrollHeight)*100)+'%</span>'
  160. }else{
  161. x.innerHTML+='<span class="tooltip">未看</span>'
  162. }
  163. })
  164. console.log('tips is loaded')
  165. },
  166. addstyle:function(){
  167. document.querySelector('.muye').innerHTML+=`<style>
  168. .tooltip {
  169. visibility: hidden; /* 初始状态下隐藏工具提示 */
  170. background-color: #555;
  171. color: #fff;
  172. text-align: center;
  173. border-radius: 5px;
  174. padding: 5px 10px;
  175. position: absolute; /* 使用绝对定位 */
  176. z-index: 1; /* 确保工具提示显示在其他元素之上 */
  177. bottom: 125%; /* 工具提示显示在按钮上方 */
  178. left: 25%;
  179. transform: translateX(-50%);
  180. opacity: 0; /* 初始状态下透明度为0 */
  181. transition: opacity 0.3s; /* 添加过渡效果 */
  182. }
  183. .chapter-item:hover .tooltip {
  184. visibility: visible; /* 鼠标悬停时显示工具提示 */
  185. opacity: 1; /* 鼠标悬停时设置透明度为1 */
  186. }
  187. </style>`
  188. },
  189. downloadimg:function(){ //after img.flat()
  190. this.onloadnum=0,
  191. this.dataUrl=[]
  192. this.loadimg=function(img){
  193. // 使用 Object.defineProperty 监听 onloadnum 的变化
  194. Object.defineProperty(downloader.loadimg, 'onloadnum', {
  195. get: function() {
  196. return this._onloadnum || 0;
  197. },
  198. set: function(value) {
  199. if (typeof value !== 'number' || isNaN(value)) {
  200. console.error('Invalid value for onloadnum:', value);
  201. return;
  202. }
  203. this._onloadnum = value;
  204. if (this._onloadnum === img.length) {
  205. downloader.loadimg.turnimgtozip();
  206. }
  207. },
  208. enumerable: true,
  209. configurable: true
  210. });
  211. img.forEach(x=>{
  212. GM_xmlhttpRequest({
  213. method: 'GET',
  214. url: x.src,
  215. responseType: 'blob', // 返回 blob
  216. onload: function(response) {
  217. if (response.status === 200) {
  218. //console.log(img.filter(e=>e.src==response.finalUrl))
  219. downloader.loadimg.dataUrl.push({
  220. name:img.filter(e=>e.src==response.finalUrl)[0].name,
  221. blob:response.response,
  222. chapter:img.filter(e=>e.src==response.finalUrl)[0].chapter,
  223. original:img.filter(e=>e.src==response.finalUrl)[0].original,
  224. render:img.filter(e=>e.src==response.finalUrl)[0].render,
  225. })
  226. downloader.loadimg.onloadnum+=1
  227. console.log('图片'+img.filter(e=>e.src==response.finalUrl)[0].name+'下载完成')
  228. }
  229. },
  230. });
  231. })
  232. },
  233. this.turnimgtozip = function() {
  234. var zip = new JSZip();
  235. this.dataUrl.forEach(e => {
  236. if (e.blob) {
  237. zip.file(e.name + '.png', e.blob, { base64: false, binary: true });
  238. } else {
  239. console.error('Blob数据未找到:', e);
  240. }
  241. });
  242. zip.generateAsync({ type: "blob" }).then(function(content) {
  243. saveAs(content, "图片下载.zip");
  244. }).catch(function(err) {
  245. console.error('生成ZIP文件时出错:', err);
  246. });
  247. };
  248. }
  249. }
  250. function move(){//移动模块
  251. var guid=gui.domElement
  252. gui.domElement.children[0].onmousedown=function(e) {
  253. if(guid.style.left==''){
  254. movep=[e.clientX-(window.innerWidth-275),e.clientY-0]//首次移动
  255. }else{
  256. movep=[e.clientX-Number(guid.style.left.replace('px','')),e.clientY-Number(guid.style.top.replace('px',''))]
  257. }
  258. window.onmove=true
  259. }
  260. document.onmouseup=function(e) {
  261. movep=[]
  262. window.onmove=false
  263. if(Number(guid.style.left.replace('px',''))<0)guid.style.left='0px';
  264. if(Number(guid.style.top.replace('px',''))<0)guid.style.top='0px';
  265. if(Number(gui.domElement.style.left.replace('px',''))+260>=windowWidth){
  266. gui.domElement.style.left=(windowWidth-260)+'px'
  267. }
  268. }
  269. document.onmousemove=function(e){
  270. if(window.onmove==true){
  271. guid.style.top=e.clientY-movep[1]+'px';
  272. guid.style.left=e.clientX-movep[0]+'px'
  273. }
  274. }
  275. guid.onmouseover=function(){
  276. if(!guid.children[0].innerText.includes('右'))guid.children[0].innerText+=' (右键可移动)';
  277. }
  278. guid.onmouseout=function(){
  279. guid.children[0].innerText='番茄阅读辅助器'
  280. }
  281. }
  282. window.reader={
  283. record:async function(){//记录阅读位置
  284. window.time=String(new Date).split(' ')
  285. var datax=thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2])
  286. if(datax.length==1){
  287. //回忆了以前的知识
  288. if(thescroll.scrollTop==0){await sleep(500)}
  289. Object.assign(thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2])[0],{
  290. date:{
  291. year:time[3],
  292. month:time[2],
  293. time:time[4],
  294. area:time[6],
  295. },
  296. chapterName:document.querySelector('.muye-reader-title').innerText,
  297. chapterid:location.pathname.split('/')[2],
  298. scrolltop:thescroll.scrollTop,
  299. scrollHeight:thescroll.scrollHeight,
  300. })
  301. }else if(datax.length==0){
  302. thedata.read.read_record.push({
  303. date:{
  304. year:time[3],
  305. month:time[2],
  306. time:time[4],
  307. area:time[6],
  308. },
  309. bookName:document.querySelector('.muye-reader-nav-title').innerText,
  310. chapterName:document.querySelector('.muye-reader-title').innerText,
  311. chapterid:location.pathname.split('/')[2],
  312. scrolltop:thescroll.scrollTop,
  313. scrollHeight:thescroll.scrollHeight,
  314. })
  315. }
  316. },
  317. onload:function(){//加载阅读位置
  318. if(thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2]).length==1){
  319. thescroll.scrollTop=thedata.read.read_record.filter(e=>e.chapterid==location.pathname.split('/')[2])[0].scrolltop
  320. console.log('记录加载')
  321. }
  322. },
  323. loadrecord:function(){//加载目录记录
  324. for(let x of document.querySelector('.reader-catalog-chapters').children){
  325. for(let xx of x.children){
  326. if(xx.className!=='volume-header'){
  327. var xxx=thedata.read.read_record.filter(e=>e.chapterid==xx.children[0].attributes[0].value)
  328. if(xxx.length==1){
  329. xx.children[0].innerHTML+='<p> 已看'+Math.round(((xxx[0].scrolltop+thescroll.clientHeight)/xxx[0].scrollHeight)*100)+'%</p>'
  330. }}
  331. }
  332. }
  333. console.log('目录记录加载')
  334. },
  335. scroll:{
  336. load:function(theparent){
  337. this.scrollInterval;
  338. this.scrollStatus = theparent.add({ status: '已停止' }, 'status').name('滚动状态');
  339. this.scrollStatus.domElement.style.color = 'red';
  340. this.scrollSpeed = theparent.add({ speed: 1 }, 'speed').name('滚动速度');
  341. this.scrollSpeed.setValue(thedata.read.scroll_speed)
  342. this.scrollSpeedsave = theparent.add({ speedsave: false }, 'speedsave').name('保存速度').onChange(function(value) {
  343. if (value==true) {
  344. thedata.read.scroll_speed=reader.scroll.scrollSpeed.getValue()
  345. console.log('保存速度:'+thedata.read.scroll_speed)
  346. fqxsydqdata.savedata()
  347. }
  348. });
  349. this.nextpage = theparent.add({ nextpage: false }, 'nextpage').name('结尾自动翻页+自动滚动').onFinishChange((value)=>{localStorage.scroll=String(value)})
  350. this.stopButton = theparent.add(this, 'start').name('开始自动滚动');
  351. },
  352. autoScroll:async function() {
  353. if (thescroll.scrollTop >= thescroll.scrollHeight - thescroll.clientHeight) {
  354. console.log('滚动以至底部')
  355. window.reader.scroll.stopAutoScroll();
  356. if(reader.scroll.nextpage['$input'].checked==true){
  357. console.log('即将开始切换')
  358. await sleep(1000)
  359. if(document.querySelectorAll('.byte-btn')[1].innerText.includes('下一章')==false){
  360. alert('现在是最新一章了~')
  361. localStorage.scroll=true
  362. }
  363. else document.querySelectorAll('.byte-btn')[1].click()
  364. }
  365. }else{
  366. thescroll.scrollTop += Math.round(reader.scroll.scrollSpeed.getValue())
  367. }
  368. },
  369. startAutoScroll:function() {
  370. this.scrollInterval = setInterval(this.autoScroll, 200);
  371. this.scrollStatus.setValue('进行中');
  372. this.stopButton.name('停止自动滚动');
  373. this.scrollStatus.domElement.style.color = 'green';
  374. },
  375. stopAutoScroll:function() {
  376. clearInterval(this.scrollInterval);
  377. this.scrollStatus.setValue('已停止');
  378. this.stopButton.name('开始自动滚动');
  379. this.scrollStatus.domElement.style.color = 'red';
  380. },
  381. "start":()=>{
  382. var x=reader.scroll
  383. if(x.scrollStatus.getValue()=='已停止'){
  384. if(String(Number(x.scrollSpeed.getValue()))=='NaN'){
  385. alert('滚动速度输入非数字')
  386. return
  387. }
  388. if(x.scrollSpeed.getValue()>=1000){
  389. alert('滚动速度输入过大\n如有需要请在脚本后台修改上限\n如有错误作者概不负责')
  390. return
  391. }
  392. console.log('滚动速度:'+Math.round(x.scrollSpeed.getValue()))
  393. x.startAutoScroll();
  394. }else{
  395. x.stopAutoScroll();
  396. }
  397. }
  398. },
  399. keyboard:function(){
  400. document.addEventListener("keyup", function (e) {
  401. delete reader.mark.keydown[e.key]
  402. })
  403. document.addEventListener("keydown", function (e) {
  404. reader.mark.keydown[e.key]=true
  405. if(e.keyCode==39||e.keyCode==37){
  406. document.querySelectorAll('.byte-btn')[[37,39].indexOf(e.keyCode)].click()
  407. if(document.querySelectorAll('.byte-btn')[1].innerText!=='下一章' && e.keyCode==39){
  408. location.pathname='/reader/'+unsafeWindow.__INITIAL_STATE__.reader.chapterData.nextItemId
  409. }
  410. }
  411. });
  412. },
  413. mark:{
  414. keydown:{},
  415. },
  416. newbookmark:function(){
  417. var ele=document.createElement('div')
  418. this.imgurl=[
  419. 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAMESURBVFhHxZe9T2JBEMBnVw5CYggY7g4TCzXa2FDYkZiACQUaNdHEf8DE1hatjDZWJgajFHYWEBu0kA8xUNgaO42FUTtz16gRg3on73aWeU8eyMEp790v2TAzhN2Z3Z3ZoQ0AmMfj+epwONwPDw9Fob+KYR4XFxffSDQdRVGcDB3o6+v7STbJwMCAQmJLGRwchO3tbUaqROdAKpVSQqEQUx0YGhoCu92OngJj5d+hXAnqnHNNrgR/g7bb21s4Pj6WtmAwCGtra29OnJ6eekiU4OKt3oF8Pi/nw3nHxsZ0c/NisWgl2TACgYAWsbpbKtxisZh6619eXkgqw9vb23+RbAptbZj5b3C3222qA11dXSQRl5eX30mUGHEJ6yEyxMmfn59/k/5f4J2dnSWSDSOZTCqjo6NykEkD09BCsmGMjIzoqp+KKFR36IA+MVtMJpORkd/c3ACO6l1geAl7e3t/kK69A2dnZ+96/S+oCxcKBRB3TdpsNhuI1Adx9DAxMeEyNPpGPD4+yjtgI73l7O/vs5OTE4a5j5Hj6O/vB7Thd06nE3hHRwc2IYaSy+UYbjsOXJjM4Pf7gd/f338h3VDwzHFU0t3dDabdAYx8dnaWtDe41Wo17TUUt74ms3ipVDKl7iOY4lNTU9p619fXn38Ns9nshwOQWSCKxIfugfpqzs3NafLu7m5DZ2oaEtEgNO1AOp1WlpeXdc+1z+cjCWBhYQFWV1eb3hGXy3XHn56e9C1KHTC6RCIBsViMLOVyvbW1xSrLttBhcXGxrhM1PaGoTg37gaWlJQWjOzo6kjouWP1WbGxswPT0tJR3dnZgcnJSiUajDXeDi77/rw6IM1bi8biU8X9CvUdKVDUmImczMzNSPz8/h8PDQwiHw/LYpFHw+qrPenZ1deXs6em5I117DasZHx+HlZWVdxevZm9vT5mfnydNj9frxWPU5mHYl2FjQLqk0onh4WFYX19vauFqNjc3lUgkQlqZmh1EB0jUoTpxcHDQ8BwbgXPV21kjcNBnEwD8AdH2P3swjPSdAAAAAElFTkSuQmCC',
  420. 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF0SURBVFhH7ZZLjoMwDIbpLGY5Ym6ARC9TLskVWPFopd6CHRXcgBVrJrZ+05ASoC2PReeTKseOY5s4ieoYfEN+OO1KFEXRIkXHAZJJkqQ9nU4Hcib9druxfQl832dJMY/HYy9vDy5VAXVRKK65C1+Qu/FfwO4FPMAnUAF1dT6jBXEc8/Ubeog2KSAIAvvDY4IjsNgZyLKMv1wwd+GhMnIieVCw4Q0kmTzDgjzx1+v1d9dD2DQNRhq8Twqoi2BrQRiGLoZ34LdoAQQlNvtflqW7aws8z9vuIaL/AHmeQxsBHVi8BUOoNNu2gD5MPwdVVb3fgsvl8vJuue7jJZjdArj1iKJodB356DtQ1/Vz1zBNUw6gQ3YMGfOq6UzNMxxFAbWDFg4lF2BibEnG5jo4ggIqM5ZYMAsUHdOM2KEOw6sVUK3PqA3TX340JzZ2tMErB5hcqEG+NmbFgS/zTGKToUIwNY04n8/nlwsQOLMC6ur8QM7Acf4AF49hCmafcDMAAAAASUVORK5CYII=',
  421. ]
  422. ele.innerHTML=
  423. `<div class="reader-toolbar-item bookmark-fqxsydq">
  424. <img src='${document.querySelectorAll('.reader-toolbar-item')[2].children[1].innerText=='夜间'?this.imgurl[0]:this.imgurl[1]}' style="width: 22px; height: 22px; top: 6px; position: relative;">
  425. <div style="top: 10px; position: relative;">书签</div>
  426. </div>`
  427. document.querySelector('.reader-toolbar div').appendChild(ele)
  428. this.ele=ele
  429. this.createBookmark=function() {
  430. if(reader.bookmark.ele1){
  431. document.body.children[8].remove();
  432. reader.bookmark.ele1=undefined
  433. return
  434. };
  435. var ele1=document.createElement('div')
  436. Object.assign(ele1.style,{
  437. position: 'absolute',
  438. height:'350px',
  439. width:'400px',
  440. maxWidth: '400px',
  441. display: 'block',
  442. top: '180px',
  443. left: '169px',
  444. transformOrigin: '100% 50% 0px',
  445. backgroundColor: '#f6f6f6',
  446. borderRadius:'20px',
  447. })
  448. ele1.innerHTML=
  449. `<div class="bookmark-title fqxsydq" style="padding: 8px; font-size: 18px; font-weight: bold; text-align: center; border-bottom: 1px solid var(--web-gray_08); height: 40px; width: 100%;">
  450. 书签
  451. <button class="bookmark-add-button" style="float: right; margin-top: 2px; margin-right: 8px; background-color: var(--web-gray_08); color: black; border: none; padding: 6px 12px; border-radius: 4px; font-size: 12px;">添加</button>
  452. </div>
  453. <div class="bookmark-body fqxsydq" style="padding: 8px; height: 310px; overflow-y: auto; overflow-x: hidden; border-radius: 0px 0px 20px 20px; position: relative;"> <!-- 添加 position: relative; -->
  454. <style>
  455. .bookmark-body ul li {
  456. padding: 6px;
  457. margin-bottom: 3px;
  458. border-bottom: 1px solid var(--web-gray_08);
  459. position: relative; /* 确保子元素的绝对定位相对于当前元素 */
  460. height: 36px;
  461. }
  462. .bookmark-body ul li:hover {
  463. background-color: var(--web-gray_08);
  464. /*transform: scale(1.1);*/
  465. box-shadow: 0 0 5px #999;
  466. display: block;
  467. }
  468. .tooltip:hover {
  469. box-shadow: 0 0 5px #999;
  470. cursor: pointer;
  471. }
  472. .tooltip {
  473. visibility: hidden; /* 初始状态下隐藏工具提示 */
  474. background-color: #555;
  475. width: 120px;
  476. height: 30px;
  477. color: #fff;
  478. text-align: center;
  479. border-radius: 5px;
  480. padding: 5px 10px;
  481. position: absolute; /* 使用绝对定位 */
  482. z-index: 1; /* 确保工具提示显示在其他元素之上 */
  483. left: 50%; /* 水平居中 */
  484. bottom: 5%; /* 工具提示显示在元素上方 */
  485. transform: translateX(-50%); /* 调整为水平居中 */
  486. opacity: 0; /* 初始状态下透明度为0 */
  487. transition: opacity 0.3s; /* 添加过渡效果 */
  488. }
  489. .bookmark-body ul li:hover .tooltip {
  490. visibility: visible; /* 鼠标悬停时显示工具提示 */
  491. opacity: 1; /* 鼠标悬停时设置透明度为1 */
  492. }
  493. </style>
  494. <ul style="list-style: none; padding: 0px; margin: 0px;">
  495. <li>
  496. <div>书签 : name 章节: name</div>
  497. <input type="text" value="" style="position: absolute; top: 4px; left: 40px; width: 80%; height: 80%; z-index: 2; border: none; display: none;">
  498. <span class="tooltip" style="left: 80px;" >传送至该章节</span>
  499. <span class="tooltip" style="left: 280px;">删除该书签</span>
  500. </li>
  501. </ul>
  502. </div>`
  503. var text=ele1.children[1].children[1].innerHTML.replaceAll(' ','').replaceAll('\n','')
  504. for(let x=0;x<7;x++){
  505. ele1.children[1].children[1].innerHTML+=text
  506. }
  507. var returndata1=reader.bookmark.loadBookmark()
  508. returndata1=='none' ? (()=>{
  509. reader.bookmark.savenewmark('none')
  510. returndata1=reader.bookmark.loadBookmark()
  511. })() : console.log('loadBookmark');
  512. (function(){
  513. returndata1.forEach(e=>{
  514. ele1.children[1].children[1].children[returndata1.indexOf(e)].children[0].innerHTML='书签 : '+e.name+' 章节: '+e.chapterName;
  515. })
  516. // 猎奇 html children还不能直接用filter和forEach
  517. Array.from(ele1.children[1].children[1].children,)
  518. .filter(e=>e.innerText.includes('章节: name')==true).forEach((x)=>{
  519. x.style.display='none'
  520. x.children[2].style.display='none'
  521. x.children[3].style.display='none'
  522. })
  523. })()
  524. ele1.children[0].children[0].addEventListener('click',(e)=>{
  525. var thisele=Array.from(ele1.children[1].children[1].children,)
  526. .filter(e=>e.innerText.includes('章节: name')==true)[0]
  527. if(e.srcElement.innerText=='确定'){
  528. thisele.children[0].innerHTML='书签 : '+thisele.children[1].value+' 章节'+unsafeWindow.__INITIAL_STATE__.reader.chapterData.title;
  529. thisele.children[1].style.display='none'
  530. thisele.children[2].style.display='block'
  531. thisele.children[3].style.display='block'
  532. var returndata2=thedata.read.bookmark.filter(e=>e.bookid==unsafeWindow.__INITIAL_STATE__.reader.chapterData.bookId)
  533. returndata2.length == 1 ? (function(){
  534. returndata2[0].bookmark.push({
  535. name:thisele.children[1].value,
  536. chapterName:unsafeWindow.__INITIAL_STATE__.reader.chapterData.title,
  537. chapterid:location.pathname.split('/')[2],
  538. scroll:thescroll.scrollTop/thescroll.scrollHeight,
  539. time:String(new Date),
  540. })
  541. fqxsydqdata.savedata()
  542. })() : console.log('有问题')
  543. e.srcElement.innerText='添加'
  544. return
  545. }
  546. thisele.style.display='block'
  547. thisele.children[0].innerHTML='章节: name'
  548. thisele.children[1].style.display='block'
  549. thisele.children[1].focus()
  550. e.srcElement.innerText='确定'
  551. },false)
  552. Array.from(ele1.children[1].children[1].children,).forEach(x=>{//传送至章节 加事件
  553. x.children[2].addEventListener('click',(e)=>{
  554. if(e.srcElement.style.display!=='none'){
  555. var returndata3=thedata.read.bookmark.filter(e=>e.bookid==unsafeWindow.__INITIAL_STATE__.reader.chapterData.bookId)[0]
  556. .bookmark[Array.from(ele1.children[1].children[1].children,).indexOf(e.srcElement.parentElement)]
  557. window.location.search='?'+returndata3.scroll
  558. window.location.pathname='/reader/'+returndata3.chapterid
  559. }
  560. })
  561. })
  562. document.body.appendChild(ele1)
  563. reader.bookmark.ele1=ele1
  564. }
  565. this.ele.addEventListener('click',this.createBookmark,false)
  566. this.loadBookmark=function(){
  567. var markdata=thedata.read.bookmark.filter(e=>e.bookid==unsafeWindow.__INITIAL_STATE__.reader.chapterData.bookId)
  568. if(markdata.length > 0){
  569. return markdata[0].bookmark
  570. }
  571. return 'none'
  572. }
  573. this.savenewmark=function(e){
  574. if(e=='none'){
  575. thedata.read.bookmark.push({
  576. bookName:unsafeWindow.__INITIAL_STATE__.reader.chapterData.bookName,
  577. bookid:unsafeWindow.__INITIAL_STATE__.reader.chapterData.bookId,
  578. author:unsafeWindow.__INITIAL_STATE__.reader.chapterData.author,
  579. bookmark:[
  580. /*{
  581. name:'',
  582. chapterName:unsafeWindow.__INITIAL_STATE__.reader.chapterData.title,
  583. chapterid:location.pathname.split('/')[2],
  584. scroll:thescroll.scrollTop/thescroll.scrollHeight,
  585. time:String(new Date),
  586. },*/
  587. ],
  588. })
  589. fqxsydqdata.savedata()
  590. }
  591. }
  592. this.onStringchange=function(){
  593. var targetNode = document.querySelectorAll('.reader-toolbar-item')[2]
  594. // 配置观察选项
  595. var config = { childList: true, characterData: true, subtree: true };
  596. // 创建一个观察器实例,并传入函数
  597. //此api性能小,不适合观察大量元素变化
  598. var observer = new MutationObserver(function(mutationsList) {
  599. for (var mutation of mutationsList) {
  600. /*if (mutation.type === 'childList') {
  601. console.log('子节点发生变化:', mutation); 即图片改变
  602. } else*/
  603. if (mutation.type === 'characterData') {
  604. //console.log('字符数据改变了:', mutation.target.nodeValue);
  605. console.log('colorchange')
  606. if(reader.bookmark.ele1){
  607. reader.bookmark.ele1.style.backgroundColor=['日间','夜间'].indexOf(mutation.target.nodeValue) == 0 ? '#404040' : '#f2f2f2';
  608. }
  609. reader.bookmark.ele.children[0].children[0].src=
  610. reader.bookmark.imgurl[[1,0][['日间','夜间'].indexOf(mutation.target.nodeValue)]]
  611. } /*1,0相反*/
  612. }
  613. });
  614. // 传入目标节点和配置选项开始观察
  615. observer.observe(targetNode, config);
  616. }
  617. }
  618. }
  619. window.fqxsydqdata={
  620. getdata:function(){
  621. if(!localStorage.fqxsydq){
  622. window.thedata={
  623. name:'番茄阅读辅助器',
  624. version:'1.540',
  625. read:{
  626. read_record:[],
  627. last_read:{},
  628. scroll_speed:1,
  629. shortcut_key:{
  630. changemark:'d',
  631. },
  632. bookmark:[
  633.  
  634. ],
  635. },
  636. download:{
  637. },
  638. }
  639. this.update('bookmark')
  640. localStorage.fqxsydq=JSON.stringify(thedata)
  641. }else{
  642. window.thedata=JSON.parse(localStorage.fqxsydq)
  643. if(!thedata.read.bookmark || !thedata.read.bookmark.length){
  644. window.thedata={
  645. name:'番茄阅读辅助器',
  646. version:'2.00',
  647. read:{
  648. read_record:thedata.read.read_record,
  649. last_read:{},
  650. scroll_speed:thedata.read.scroll_speed,
  651. shortcut_key:{
  652. changemark:'d',
  653. },
  654. bookmark:[
  655.  
  656. ],
  657. },
  658. download:{
  659. },
  660. }
  661. this.savedata()
  662. alert('原版本数据格式低,已更新,原数据删了,请重新添加书签')
  663. }
  664. }
  665. },
  666. savedata:function(){
  667. localStorage.fqxsydq=JSON.stringify(thedata)
  668. },
  669. }
  670. window.main = {
  671. "copybook" : async()=>{
  672. data=''
  673. img=[]
  674. if(Number(document.querySelectorAll('.widget')[2].children[0].value)<60){
  675. var b=confirm('小于60毫秒作者建议请一下后台\n开的时候玩手机就行了\n作者亲测50毫秒间隔下载也不会出错')
  676. if(!b==true)return;
  677. }
  678. console.log('下载模式:'+document.querySelectorAll('.widget')[1].children[0].value)
  679. var type=['原版','机改1','机改2'].indexOf(document.querySelectorAll('.widget')[1].children[0].value)
  680. document.querySelectorAll('.tooltip').forEach(x=>x.remove())
  681. alert('请等待提示,现开始复制\n可通过控制台查看进度\n会暂时去除显示进度功能')
  682. globalThis.a=document.querySelector('.page-directory-content')
  683. globalThis.num1=1
  684. for(let x of a.children){
  685. await downloader.dispose(x,'computer')
  686. await sleep(150)
  687. }
  688. await sleep(3000)
  689. await downloader.downloadd(type)
  690. downloader.loadrecord()
  691. },
  692. "loadhistory":async()=>{
  693. if(Object.values(thedata.read.last_read).length==3){
  694. if(await confirm('上次阅读书目为'+thedata.read.last_read.bookName+' 章节名称:'+thedata.read.last_read.bookName+' 点击确认即刻前往')){
  695. location.href='https://fanqienovel.com/reader/'+thedata.read.last_read.chapterid
  696. }
  697. }
  698. },
  699. };
  700. window.gui = new lil.GUI({ title: '番茄阅读辅助器' });
  701. window.gui.domElement.style.userSelect = 'none';
  702. move()
  703. fqxsydqdata.getdata()
  704. if(location.href.includes('force_mobile=1')){
  705. alert('暂不支持手机排版的下载\n如使用电脑请保证长宽比例不低于1\n防止排版进入手机格式')
  706. return
  707. }
  708. var page1
  709. if(location.href.includes('/page/')){
  710. page1 = gui.addFolder('复制')
  711. page1.add(main,'copybook').name('复制本书全文 (仅支持电脑)')
  712. page1.add({setting:1},'setting',{'原版':1,'机改1':2,'机改2':3}).name('下载设置')
  713. page1.add({a:100},"a").min(1).name('下载速度')
  714. document.querySelectorAll('.controller')[1].innerHTML+='<div class="question">?</div>'
  715. document.querySelector('.question').addEventListener('click',()=>{
  716. alert('原版:下载原版章节\n机翻1:下载机翻1章节\n机翻2:下载机翻2章节\n机翻1效果如下\n第一卷\n第1章\n第2章\n......\n第二卷\n第100章...\n机翻2\n第一卷\n第1章\n第2章\n......\n第二卷\n第1章')
  717. })
  718. downloader.loadrecord()
  719. downloader.addstyle()
  720. }
  721. else if(location.href.includes('/reader/')){
  722. window.thescroll=document.querySelector('.muye-reader')
  723. reader.onload()
  724. window.scrollhref=location.pathname
  725. thescroll.onscroll=function(e){
  726. if(scrollhref!==location.pathname){
  727. reader.onload()
  728. window.scrollhref=location.pathname
  729. return
  730. }
  731. reader.record()
  732. fqxsydqdata.savedata()
  733. }
  734. document.querySelectorAll('.reader-toolbar-item')[1].addEventListener('click',async()=>{
  735. await sleep(1500)
  736. reader.loadrecord()
  737. })
  738. page1 = gui.addFolder('阅读')
  739. var page1_1 = page1.addFolder('滚动').close()
  740. reader.bookmark=new reader.newbookmark()//newbookmark
  741. reader.bookmark.onStringchange()
  742. reader.scroll.load(page1_1)
  743. reader.keyboard()
  744. if(localStorage.scroll=='true'){
  745. reader.scroll.stopButton.$button.click()
  746. reader.scroll.nextpage.$input.checked=true
  747. };
  748. window.onunload=function(){
  749. thedata.read.last_read={
  750. chapterid:location.pathname.split('/')[2],
  751. bookName:unsafeWindow.__INITIAL_STATE__.reader.chapterData.bookName,
  752. chapterName:document.querySelector('.muye-reader-title').innerText,
  753. }
  754. fqxsydqdata.savedata()
  755. }
  756. }
  757. gui.add(main,'loadhistory').name('返回上次阅读')
  758. gui.add({'bookshelf':()=>{location.href='https://fanqienovel.com/bookshelf'}},'bookshelf').name('返回书架')
  759. })();

QingJ © 2025

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