📖 精确搜索

https://m.jjwxc.net/assort#

分享者: guaner001125 (317)发布时间: 04/10 10:31

更改加载页面为滚动加载
二维码导入
{
    "articleStyle": 0,
    "customOrder": 24,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n\t\"referer\":\"http:\/\/android.jjwxc.net\/?v=357\",\n\t\"versionCode\":\"357\",\n\t\"versiontype\":\"reading\",\n  \"User-Agent\": \"Dalvik\/2.1.0\"\n}",
    "injectJs": "\nlet previousUrl = \"\";\nlet currentUrl = '';\nlet bqUrl = \"\";\nlet currentOffset = 0;\nlet totalPages = 1;\nlet isLoading = false;\nlet hasMore = true;\nlet hasPrevious = false;\nlet scrollDebounceTimer = null;\n\n\/\/ 标签编解码\nfunction encode(str) {\n    str = str.replace(\/https:.*?bq=\/g,'');\n    return btoa(encodeURI(str));\n}\n\nfunction decode(str) {\n    str = \"https:\/\/android.jjwxc.net\/search\/getSearchForKeyWords?offset=0&limit=20&bq=\" + atob(str);\n    return str;\n}\n\n\/\/ 书籍定位\nfunction recordBookPosition(novelid,offset) {\n    let previousUrl = sessionStorage.getItem('previousUrl');\n    sessionStorage.setItem('bookPosition', JSON.stringify({\n        url:previousUrl,\n        novelid: novelid,\n        offset: offset    \n    }));\n}\n\nfunction restoreBookPosition() {\n    const bookPosition = sessionStorage.getItem('bookPosition');\n    if (!bookPosition) return;\n    \n    let { url, novelid, offset, timestamp } = JSON.parse(bookPosition);\n    const pUrl = new URL(url);\n    pUrl.searchParams.set('offset', offset);\n    currentOffset = offset;\n    fetchAndRender(pUrl.toString(), function(error) {\n    if (error) {\n        console.error('加载失败,无法滚动:', error);\n        return;\n    }\n    \n    const bookElement = document.querySelector(`.book[data-id=\"${novelid}\"]`);\n    if (bookElement) {\n        updateCurrentPage()\n        window.scrollTo({\n            top: bookElement.offsetTop - 100,\n            behavior: 'auto'\n        });\n    }\n});\n    \n}\n\nfunction fetchAndRender(url, callback) {\n    showLoadingMessage();\n    isLoading = true;\n    sessionStorage.setItem('previousUrl',url);\n    fetch(url)\n        .then(response => response.json())\n        .then(jsonData => {\n            currentUrl = url;\n            totalPages = jsonData.total_page;\n            currentOffset = parseInt(new URL(url).searchParams.get('offset')) || 0;\n            hasMore = (Math.floor(currentOffset \/ 20) + 1) < jsonData.total_page;\n            hasPrevious = currentOffset > 0; \/\/ 设置是否有上一页\n            sessionStorage.setItem('previousUrl',url);\n            generatePageContent(jsonData,currentOffset);\n            addStyles();\n            \n            if (typeof callback === 'function') {\n                callback(null, jsonData);\n            }\n        })\n        .catch(error => {\n            console.error('加载失败:', error);\n            if (typeof callback === 'function') {\n                callback(error);\n            }\n        })\n        .finally(() => {\n            isLoading = false;\n            hideLoadingMessage();\n            bookPosition = sessionStorage.getItem('bookPosition');        \n            sessionStorage.removeItem('bookPosition');        \n            if (!bookPosition) {\n                window.scrollTo(0,0); \t\n                return;\n            }\n        });\n}\n\n\/\/ 下拉加载\nfunction initScrollListener() {\n    \/\/ 使用被动事件监听器提高滚动性能\n    window.addEventListener('scroll', handleScroll, { passive: true });\n}\n\nfunction handleScroll() {\n    \/\/ 防抖处理\n    clearTimeout(scrollDebounceTimer);\n    scrollDebounceTimer = setTimeout(() => {\n        if (!isLoading) {\n            updateCurrentPage();\n        }\n        \n        \/\/ 检查是否到达边界\n        checkScrollBoundaries();\n    }, 50);\n}\n\nfunction checkScrollBoundaries() {\n    if (isLoading) return;\n    \n    const scrollPosition = window.scrollY;\n    const documentHeight = document.body.offsetHeight;\n    const windowHeight = window.innerHeight;\n    \n    \/\/ 检查是否到达底部\n    if (scrollPosition + windowHeight >= documentHeight - 100 && hasMore) {\n        loadNextPage();\n    }\n    \n    \/\/ 检查是否到达顶部\n    if (scrollPosition <= 100 && hasPrevious) {\n        loadPreviousPage();\n    }\n}\n\nfunction loadPreviousPage() {\n    if (isLoading) return;\n    \n    isLoading = true;\n    document.getElementById('loading').style.display = 'block';\n    \n    const newOffset = Math.max(0, currentOffset - 20);\n    const url = new URL(currentUrl);\n    url.searchParams.set('offset', newOffset);\n    \n    \/\/ 保存当前滚动位置\n    const scrollPositionBefore = window.scrollY;\n    \n    fetch(url.toString())\n        .then(response => response.json())\n        .then(jsonData => {\n            \/\/ 使用requestAnimationFrame确保平滑加载\n            requestAnimationFrame(() => {\n                \/\/ 加载新内容\n                prependBookElements(jsonData, newOffset);\n                \n                \/\/ 更新状态\n                currentOffset = newOffset;\n                updateCurrentPage();\n                hasMore = (Math.floor(newOffset \/ 20) + 1) < jsonData.total_page;\n                hasPrevious = newOffset > 0;\n                \n                \/\/ 计算并保持滚动位置\n                const newBooks = document.querySelectorAll('.book');\n                if (newBooks.length > 0) {\n                    \/\/ 滚动到新加载内容的最后一本(即之前那页的第一本)\n                    const targetBook = newBooks[jsonData.items.length - 1];\n                    if (targetBook) {\n                        const targetPosition = targetBook.offsetTop +100; \/\/ 留出一些顶部空间\n                        \n                        \/\/ 使用平滑滚动\n                        window.scrollTo({\n                            top: targetPosition,\n                            behavior: 'auto'\n                        });\n                    }\n                }\n            });\n        })\n        .catch(error => {\n            console.error('加载上一页失败:', error);\n        })\n        .finally(() => {\n            isLoading = false;\n            document.getElementById('loading').style.display = 'none';\n        });\n}\n\n\/\/ 优化后的加载下一页函数\nfunction loadNextPage() {\n    if (isLoading) return;\n    \n    isLoading = true;\n    document.getElementById('loading').style.display = 'block';\n    \n    const newOffset = currentOffset + 20;\n    const url = new URL(currentUrl);\n    url.searchParams.set('offset', newOffset);\n    \n    fetch(url.toString())\n        .then(response => response.json())\n        .then(jsonData => {\n            requestAnimationFrame(() => {\n                currentOffset = newOffset;\n                appendBookElements(jsonData, newOffset);\n                updateCurrentPage();\n                hasMore = (Math.floor(newOffset \/ 20) + 1) < jsonData.total_page;\n            });\n        })\n        .catch(error => {\n            console.error('加载下一页失败:', error);\n        })\n        .finally(() => {\n            isLoading = false;\n            document.getElementById('loading').style.display = 'none';\n        });\n}\n\nfunction createBookElement(item,offset){\nlet bookDiv = document.createElement('div');\n        bookDiv.className = 'book';\n        bookDiv.setAttribute('data-id', item.novelid);\n        bookDiv.setAttribute('data-offset', offset);\n\n        bookDiv.innerHTML = `\n            <div class=\"bookdes\">\n                <div class=\"pic\"><img src=\"${item.cover}\" referrerpolicy=\"no-referrer\"><\/div>\n                <div class=\"details\">\n                    <p class=\"bookname\">\n                        <span class=\"name\"><a href=\"https:\/\/m.jjwxc.net\/book2\/${item.novelid}\">${item.novelname}<\/a><\/span>\n                        <br>\n                        <span class=\"author\">——${item.authorname}<\/span>\n                    <\/p>\n                    <p class=\"tag\">⭐️ ${item.novelSizeformat}字•${item.novelstep === '2' ? '<span style=\"color:red\">已完结<\/span>' : '<span style=\"color:blue\">连载中<\/span>'}<br><br>📖 ${item.novelintroshort}<br><br>🔖 ${item.novelClass}<br><br>🏷 <span style=\"color:green\">${item.tags}<\/span><\/p>\n                <\/div>\n            <\/div>\n        `;\n        \n        const link = bookDiv.querySelector('a');\n        link.addEventListener('click', (e) => {\n            e.preventDefault();\n            recordBookPosition(item.novelid, offset);\n            window.location.href = link.href;\n        });\nreturn bookDiv\n}\n\n\n\nfunction prependBookElements(data, offset) {\n    const bookContainer = document.getElementById('bookContainer');\n    const fragment = document.createDocumentFragment();   \n    data.items.forEach((item, index) => {       \n        let bookDiv = createBookElement(item,offset)\n        fragment.appendChild(bookDiv);\n    });    \n    bookContainer.insertBefore(fragment, bookContainer.firstChild);\n}\n\n\n\/\/ 书籍列表生成\nfunction createBookElements(data,offset) {\n    const bookContainer = document.getElementById('bookContainer');\n    bookContainer.innerHTML = '';\n    data.items.forEach((item, index) => {\n        let bookDiv = createBookElement(item,offset)\n        bookContainer.appendChild(bookDiv);     \n    });\n}\n\nfunction appendBookElements(data,offset) {\n    const bookContainer = document.getElementById('bookContainer');\n    data.items.forEach((item, index) => {\n        let bookDiv = createBookElement(item,offset)\n        bookContainer.appendChild(bookDiv);\n    });\n}\n\n\/\/ 页面操作\nfunction updateUrlParam(key, value) {\n    const url = new URL(currentUrl);\n    url.searchParams.set(key, value);\n    url.searchParams.set('offset', 0);\n    currentOffset = 0;\n    updateCurrentPage()\n    fetchAndRender(url.toString());\n}\n\nfunction updateOffset(delta) {\n    const url = new URL(currentUrl);\n    const newOffset = Math.max(0, currentOffset + delta);\n    currentOffset = newOffset;\n    url.searchParams.set('offset', newOffset);\n    fetchAndRender(url.toString());\n}\n\nfunction jumpToPage() {\n    const pageInput = document.querySelector('.page-input');\n    const page = parseInt(pageInput.value);\n    if (isNaN(page) || page < 1 || page > totalPages) {\n        alert(`请输入有效的页码(1-${totalPages})`);\n        return;\n    }\n    \n    currentOffset = (page - 1) * 20;\n    const url = new URL(currentUrl);\n    url.searchParams.set('offset', currentOffset);\n    fetchAndRender(url.toString());\n}\n\nfunction updateCurrentPage() {\n    const books = document.querySelectorAll('.book');\n    if (books.length === 0) return;\n    \n    \/\/ 使用IntersectionObserver检测可见书籍\n    const observer = new IntersectionObserver((entries) => {\n        entries.forEach(entry => {\n            if (entry.isIntersecting) {\n                const bookOffsetAttr = entry.target.getAttribute('data-offset');\n                \nconst bookOffset = bookOffsetAttr !== null ? parseInt(bookOffsetAttr) : currentOffset;\n\n                const currentPage = Math.floor(bookOffset \/ 20) + 1;\n                \n                \/\/ 只有当页码确实改变时才更新DOM\n                const currentDisplay = document.querySelector('.current-page').textContent;\n                if (currentDisplay !== currentPage.toString()) {\n                    document.querySelector('.current-page').textContent = currentPage;\n                    document.querySelector('.current').textContent = currentPage;\n                    currentOffset = bookOffset;\n                }\n            }\n        });\n    }, {\n        threshold: 0.5 \/\/ 当书籍50%可见时触发\n    });\n    \n    \/\/ 观察所有书籍\n    books.forEach(book => {\n        observer.observe(book);\n    });\n    \n    \/\/ 清理观察器\n    return () => {\n        observer.disconnect();\n    };\n}\n\n\n\/\/ 辅助函数\nfunction showLoadingMessage() {\n    const loadingDiv = document.createElement('div');\n    loadingDiv.id = 'loading-message';\n    loadingDiv.style.position = 'fixed';\n    loadingDiv.style.top = '20px';\n    loadingDiv.style.left = '50%';\n    loadingDiv.style.transform = 'translateX(-50%)';\n    loadingDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';\n    loadingDiv.style.color = 'white';\n    loadingDiv.style.padding = '10px 20px';\n    loadingDiv.style.borderRadius = '5px';\n    loadingDiv.style.zIndex = '1000';\n    loadingDiv.textContent = '正在加载,请稍候...';\n    document.body.appendChild(loadingDiv);\n}\n\nfunction hideLoadingMessage() {\n    const loadingDiv = document.getElementById('loading-message');\n    if (loadingDiv) loadingDiv.remove();\n}\n\nfunction generateFinalUrl(formData) {\n    const variables = {};\n    for (let [key, value] of formData.entries()) {\n        const variableName = key.replace(\/\\d+\/g, '');\n        if (!variables[variableName]) {\n            variables[variableName] = [];\n        }\n        variables[variableName].push(value);\n    }\n\n    for (const key in variables) {\n        variables[key] = variables[key].join(',');\n    }\n\n    return `https:\/\/android.jjwxc.net\/search\/getSearchForKeyWords?offset=0&limit=20&bq=${variables.bq || ''}&removetags=${variables.removebq || ''}&notlikecollectionTypes=${variables.notlikecollectiontypes || ''}&fw=${variables.fw || ''}&yc=${variables.yc || ''}&xx=${variables.xx || ''}&sd=${variables.sd || ''}&lx=${variables.lx || ''}&mainview=${variables.mainview || ''}&fbsj=${variables.fbsj || ''}&novelbefavoritedcount=${variables.novelbefavoritedcount || ''}&isfinish=${variables.isfinish || ''}&collectionTypes=${variables.collectiontypes || ''}&searchkeyWords=${variables.searchkeywords || ''}`;\n}\n\n\/\/ 页面生成\/\nfunction generatePageContent(jsonData,offset) {\n    document.documentElement.innerHTML = `\n          <!-- 悬浮按钮组 -->\n    <div class=\"float-buttons\">\n        <div class=\"button-group\">\n                    <!-- 页码控制面板 -->\n            <div class=\"page-control\">\n                <div class=\"page-info\">\n                    <span class=\"current-page\">1<\/span>\n                    <div class=\"divider\"><\/div>\n                    <span class=\"total-pages\">${jsonData.total_page}<\/span>\n                <\/div>\n                <div class=\"page-jump\">\n                    <input type=\"number\" min=\"1\" max=\"${jsonData.total_page}\" value=\"1\" class=\"page-input\">\n                    <button class=\"go-btn\">GO<\/button>\n                <\/div>\n            <\/div>\n            <!-- 功能按钮(从下到上顺序) -->\n            <button class=\"func-btn home\" title=\"返回首页\">⌂<\/button>\n            <button class=\"func-btn bottom\" title=\"页面底部\">↓<\/button>\n            <button class=\"func-btn top\" title=\"页面顶部\">↑<\/button>\n            \n\n        <\/div>\n        \n        <!-- 主按钮 - 深绿色圆形 -->\n        <button class=\"main-btn\" title=\"展开功能\">\n            <span class=\"current\">1<\/span>\n            <div class=\"divider\"><\/div>\n            <span class=\"total\">${jsonData.total_page}<\/span>\n        <\/button>\n    <\/div>\n    \n            <div class=\"center\" style=\"text-align: center;\">\n                按 <select name=\"sortType\" id=\"orderstr\">\n                    <option value=\"2\">积分<\/option>\n                    <option value=\"1\">最近更新<\/option>\n                    <option value=\"3\">最新发表<\/option>\n                    <option value=\"5\">字数<\/option>\n                    <option value=\"4\">收藏数<\/option>\n                    <option value=\"10\">完结高分<\/option>\n                <\/select> 排序\n                <span style=\"margin: 0 10px;\"> | <\/span>\n                只显示 <select name=\"isfinish\" id=\"isfinish\">\n                    <option value=\"0\">无限制<\/option>\n                    <option value=\"1\">连载<\/option>\n                    <option value=\"2\">完结<\/option>\n                <\/select>\n            <\/div>\n        <div style=\"height: 60px;\"><\/div>\n        <br>\n        <div id=\"bookContainer\" class=\"book-container\"><\/div>\n        <div id=\"loading\" style=\"text-align: center; padding: 10px; display: none;\">\n            正在加载更多...\n        <\/div>\n    `;\n\n    const sortTypeSelect = document.getElementById(\"orderstr\");\n    const isFinishSelect = document.getElementById(\"isfinish\");\n    const urlParams = new URLSearchParams(currentUrl.split('?')[1]);\n            \/\/ 获取DOM元素\n    const mainBtn = document.querySelector('.main-btn');\n    const floatButtons = document.querySelector('.float-buttons');\n    const totalPagesEl = document.querySelector('.total-pages');\n    const pageInput = document.querySelector('.page-input');\n    const pageSections = document.querySelectorAll('.page-section');\n    const homeBtn = document.querySelector('.func-btn.home');\n    const topBtn = document.querySelector('.func-btn.top');\n    const bottomBtn = document.querySelector('.func-btn.bottom');\n    \n            \/\/ 设置总页数\n        totalPages = jsonData.total_page; \/\/ 示例使用六位数页码\n        totalPagesEl.textContent = totalPages;\n        pageInput.max = totalPages;\n        \n        \/\/ 检测是否为长页码\n        if (totalPages >= 10000) {\n            floatButtons.classList.add('long-page');\n        }\n        \n        \/\/ 切换按钮组显示\n        mainBtn.addEventListener('click', function(e) {\n            e.stopPropagation();\n            floatButtons.classList.toggle('expanded');\n            mainBtn.style.display = 'none';\n            \n        });\n        \n        \/\/ 点击页面其他区域收起按钮组\n        document.addEventListener('click', function() {\n            floatButtons.classList.remove('expanded');\n            mainBtn.style.display = 'flex';\n        });\n        \n        \/\/ 阻止按钮组内部点击事件冒泡\n        document.querySelector('.button-group').addEventListener('click', function(e) {\n            e.stopPropagation();\n        });\n        \n        \/\/ 跳转按钮事件\n        document.querySelector('.go-btn').addEventListener('click', jumpToPage);\n        \n\n        \/\/ 功能按钮事件\n        homeBtn.addEventListener('click', function() {\n            sessionStorage.setItem('previousUrl', \"\");\n            window.location.reload();\n        });\n        \n        topBtn.addEventListener('click', function() {\n            window.scrollTo({top: 0, behavior: 'smooth'});\n            floatButtons.classList.remove('expanded');\n            mainBtn.style.display = 'flex';\n        });\n        \n        bottomBtn.addEventListener('click', function() {\n            window.scrollTo({top: document.body.scrollHeight-100, behavior: 'smooth'});\n            floatButtons.classList.remove('expanded');\n            mainBtn.style.display = 'flex';\n        });\n        \n    sortTypeSelect.value = urlParams.get('sortType') || '2';\n    isFinishSelect.value = urlParams.get('isfinish') || '0';\n\n    sortTypeSelect.onchange = () => updateUrlParam('sortType', sortTypeSelect.value);\n    isFinishSelect.onchange = () => updateUrlParam('isfinish', isFinishSelect.value);\n\n    initScrollListener();\n    createBookElements(jsonData,offset);\n    updateCurrentPage();\n    \n    const checkScrollable = () => {\n        if (document.body.scrollHeight <= window.innerHeight) {\n            \/\/ 如果内容不足以滚动,尝试加载更多\n            if (hasMore) {\n                loadNextPage();\n            } else if (hasPrevious) {\n                \/\/ 或者尝试加载上一页(如果有)\n                loadPreviousPage();\n            }\n        }\n    };\n    \n    \/\/ 初始检查\n    checkScrollable();\n}\nwindow.addEventListener('beforeunload', () => {\n    window.removeEventListener('scroll', handleScroll);\n    window.removeEventListener('resize', checkScrollable);\n});\n        \n        \n\/\/ 标签管理\nif(\/#$\/.test(window.location.href)){\n    bqUrl = window.location.href;\n    const urls = bqUrl.split('#');\n    const buttonData = urls.slice(1).filter(part => part.trim() !== '');\n\n    const buttonContainer = document.createElement('div');\n    buttonContainer.style.position = 'fixed';\n    buttonContainer.style.bottom = '50px';\n    buttonContainer.style.right = '20px';\n    buttonContainer.style.zIndex = '1000';\n    buttonContainer.style.display = 'flex';\n    buttonContainer.style.flexDirection = 'column';\n    buttonContainer.style.gap = '10px';\n    document.body.appendChild(buttonContainer);\n\n    buttonData.forEach((data, index) => {\n        const [label, url] = data.split('@');\n        const button = document.createElement('button');\n        button.textContent = decodeURIComponent(label) || `标签${index + 1}`;\n        button.style.padding = '5px 10px';\n        button.style.backgroundColor = '#007BFF';\n        button.style.color = 'white';\n        button.style.border = 'none';\n        button.style.borderRadius = '5px';\n        button.style.cursor = 'pointer';\n        button.addEventListener('click', () => fetchAndRender(decode(url)));\n        buttonContainer.appendChild(button);\n    });\n\n    const button = document.createElement('button');\n    button.textContent = '生成标签';\n    button.style.position = 'fixed';\n    button.style.bottom = '20px';\n    button.style.right = '20px';\n    button.style.zIndex = '1000';\n    button.style.padding = '5px 10px';\n    button.style.backgroundColor = '#007BFF';\n    button.style.color = 'white';\n    button.style.border = 'none';\n    button.style.borderRadius = '5px';\n    button.style.cursor = 'pointer';\n    document.body.appendChild(button);\n\n    button.addEventListener('click', () => {\n        const form = document.getElementsByTagName('form')[1];\n        const formData = new FormData(form);\n        const finalUrl = generateFinalUrl(formData);\n        \n        const overlay = document.createElement('div');\n        overlay.style.position = 'fixed';\n        overlay.style.top = '0';\n        overlay.style.left = '0';\n        overlay.style.width = '100%';\n        overlay.style.height = '100%';\n        overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';\n        overlay.style.zIndex = '1001';\n        overlay.style.display = 'flex';\n        overlay.style.justifyContent = 'center';\n        overlay.style.alignItems = 'center';\n        \n        const dialog = document.createElement('div');\n        dialog.style.backgroundColor = 'white';\n        dialog.style.padding = '20px';\n        dialog.style.borderRadius = '10px';\n        dialog.style.width = '80%';\n        dialog.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.3)';\n        dialog.style.textAlign = 'center';\n\n        const promptText = document.createElement('p');\n        promptText.textContent = '复制标签网址到【源URL】保存标签';\n        promptText.style.margin = '10px 0';\n        promptText.style.fontSize = '14px';\n        promptText.style.color = '#333';\n        dialog.appendChild(promptText);\n\n        const urlTextarea = document.createElement('textarea');\n        urlTextarea.value = `标签名@${encode(finalUrl)}#`;\n        urlTextarea.style.width = '90%';\n        urlTextarea.style.height = '100px';\n        urlTextarea.style.padding = '10px';\n        urlTextarea.style.margin = '10px';\n        urlTextarea.style.outline = 'none';\n        urlTextarea.style.border = 'none';\n        urlTextarea.style.resize = 'none';\n        urlTextarea.readOnly = true;\n        dialog.appendChild(urlTextarea);\n\n        const copyButton = document.createElement('button');\n        copyButton.textContent = '一键复制';\n        copyButton.style.margin = '10px';\n        copyButton.style.padding = '10px 20px';\n        copyButton.style.backgroundColor = '#28a745';\n        copyButton.style.color = 'white';\n        copyButton.style.border = 'none';\n        copyButton.style.borderRadius = '5px';\n        copyButton.style.cursor = 'pointer';\n        copyButton.addEventListener('click', () => {\n            urlTextarea.select();\n            document.execCommand('copy');\n            alert('已复制到剪贴板!');\n            document.body.removeChild(overlay);\n        });\n        dialog.appendChild(copyButton);\n\n        const closeButton = document.createElement('button');\n        closeButton.textContent = '关闭';\n        closeButton.style.margin = '10px';\n        closeButton.style.padding = '10px 20px';\n        closeButton.style.backgroundColor = '#dc3545';\n        closeButton.style.color = 'white';\n        closeButton.style.border = 'none';\n        closeButton.style.borderRadius = '5px';\n        closeButton.style.cursor = 'pointer';\n        closeButton.addEventListener('click', () => {\n            document.body.removeChild(overlay);\n        });\n        dialog.appendChild(closeButton);\n\n        overlay.appendChild(dialog);\n        document.body.appendChild(overlay);\n    });\n\n    const forms = document.getElementsByTagName('form')[1];\n    restoreBookPosition();\n    forms.addEventListener('submit', function(event) {\n        event.preventDefault();\n        const formData = new FormData(forms);\n        currentUrl = generateFinalUrl(formData);\n        previousUrl = currentUrl;\n        currentOffset = 0;\n        fetchAndRender(currentUrl);\n    });\n}\n\n\/\/ 书籍详情页按钮\nif (\/m\\.jjwxc\\.net\\\/book2\\\/\\d+\/.test(window.location.href)) {\n    document.getElementById(\"app\").remove();\n    const bookid = window.location.href.split('\/').pop();\n    const booksrc = `legado:\/\/import\/addToBookshelf?src=${encodeURIComponent(`http:\/\/app-cdn.jjwxc.net\/androidapi\/novelbasicinfo?novelId=${bookid}`)}`;\n    const title = document.querySelector(\".big.o\").innerText.replace(\/首页>\/, '');\n    const author = document.querySelector(\".authorname-content a\").innerText;\n\n    createButton(title, \"addBookshelf\", 14, booksrc);\n    createButton(title, \"bookName\", 18);\n    createButton(author, \"bookAuthor\", 22);\n}\n\nfunction createButton(name, type, top, url) {\n    const typeButton = type === \"bookName\" ? \"搜索书名\" : \n                      type === \"bookAuthor\" ? \"搜索作者\" : \"加入书架\";\n    const query = `${type}=${name}`;\n    const href = url ? `${url}#${query}` : `${window.location.pathname}?${query}`;\n    const button = document.createElement('a');\n    button.href = href.replace(\/#addBookshelf.*\/, '');\n    button.innerHTML = `\n        <button style=\"\n            outline: none; \n            position: fixed; \n            top: ${top}%; \n            right: 7%; \n            z-index: 999; \n            border-radius: 15px; \n            color: #166188;\n            border: 0px solid #000;\n            background: #E6F3F5;\n            padding: 4px 6px;\n            box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);\n        \">\n            <b>${typeButton}<\/b>\n        <\/button>\n    `;\n    document.body.appendChild(button);\n}\n\n\/\/ 样式\nfunction addStyles() {\n    const style = document.createElement('style');\n    style.innerHTML = `\n    .center {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    background: white; \/* 添加背景色避免文字重叠 *\/\n    z-index: 999; \/* 确保在最上层 *\/\n    padding: 10px 0; \/* 适当内边距 *\/\n    box-shadow: 0 2px 5px rgba(0,0,0,0.1); \/* 可选:添加阴影效果 *\/\n}\n\n        a:link { color: #415E44; }\n        a:visited { color: #8EB28B; }\n        button, select, input {\n            background: #E9F5F3;\n            color: green;\n            font-weight: bold;\n            border-radius: 15px;\n            border: 0px solid #000;\n            padding: 5px 10px;\n            box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);\n        }\n        \/* 悬浮按钮容器 *\/\n        .float-buttons {\n            position: fixed;\n            right: 10px;\n            bottom: 10px;\n            display: flex;\n            flex-direction: column-reverse;\n            align-items: center;\n            gap: 8px;\n            z-index: 999;\n        }\n       \n        \/* 主按钮 - 深绿色圆形 *\/\n        .main-btn {\n            width: 50px;\n            height: 50px;\n            border-radius: 50%;\n            background: #E9F5F3;\n            color: green;\n            border: none;\n            cursor: pointer;\n            box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            font-size: 12px;\n            outline: none;\n            -webkit-tap-highlight-color: transparent;\n            transition: all 0.3s ease;\n            padding: 5px 2px;\n            position: relative;\n        }\n        \n        \/* 当前页和总页数颜色区分 *\/\n        .main-btn .current {\n            color: green; \/* 亮黄色突出当前页 *\/\n            font-weight: bold;\n            margin-bottom: 2px;\n        }\n        \n        .main-btn .total {\n            color: rgba(0, 0, 0, 0.8); \/* 半透明白色显示总页数 *\/\n            font-size: 0.9em;\n            margin-top: 2px;\n        }\n        \n        \/* 分割线 *\/\n        .main-btn .divider {\n            width: 60%;\n            height: 1px;\n            background: green;\n            margin: 3px 0;\n        }\n        \n        \/* 功能按钮容器 - 默认隐藏 *\/\n        .button-group {\n            display: none;\n            flex-direction: column-reverse;\n            align-items: center;\n            gap: 8px;\n        }\n        \n        \/* 展开时显示 *\/\n        .expanded .button-group {\n            display: flex;\n            \n        }\n        \n        \/* 功能按钮样式 *\/\n        .func-btn {\n            width: 50px;\n            height: 50px;\n            border-radius: 50%;\n            background: #495057;\n            color: white;\n            border: none;\n            cursor: pointer;\n            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.7);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-size: 18px;\n            outline: none;\n            \n       \n            \n        }\n        \n        \/* 不同功能按钮颜色 *\/\n        .func-btn.home { background: #9B5F64; } \/* 红色 *\/\n        .func-btn.bottom { background: #8DA371; } \/* 绿色 *\/\n        .func-btn.top { background: #67749A; } \/* 蓝色 *\/\n        \n        \/* 页码控制面板 *\/\n        .page-control {\n            background: #E9F5F3;\n            color: white;\n            padding: 10px;\n            border-radius: 25px;\n            font-size: 14px;\n            box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            width: 30px;\n            \n        }\n        \n        .page-info {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            margin-bottom: 8px;\n            font-size: 12px;\n            line-height: 1.3;\n            position: relative;\n            width: 100%;\n        }\n        \n        \/* 控制面板中的分割线 *\/\n        .page-info .divider {\n            width: 90%;\n            height: 1px;\n            background: green;\n            margin: 4px 0;\n        }\n        \n        \/* 控制面板中的页码颜色区分 *\/\n        .page-info .current-page {\n            color: green; \/* 亮黄色 *\/\n            font-weight: bold;\n            font-size: 14px;\n        }\n        \n        .page-info .total-pages {\n            color: rgba(0, 0, 0, 0.6); \/* 半透明白色 *\/\n            font-size: 11px;\n        }\n        \n        .page-jump {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            width: 100%;\n        }\n        \n        .page-jump input {\n            width: 30px;\n            padding: 6px;\n            border: none;\n            border-radius: 15px;\n            text-align: center;\n            outline: none;\n            font-size: 12px;\n            margin-bottom: 6px;\n            background: #f8f9fa;\n        }\n        \n        .page-jump button {\n            width: 30px;\n            height: 25px;\n            background: #2b8a3e;\n            color: white;\n            border: none;\n            border-radius: 15px;\n            cursor: pointer;\n            font-size: 12px;\n            transition: background 0.2s;\n        }\n        \n        .page-jump button:hover {\n            background: #2f9e44;\n        }\n        \n        \/* 按钮悬停效果 *\/\n        .main-btn:hover, .func-btn:hover {\n            transform: translateY(-3px);\n            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25);\n        }\n        \n        \/* 按钮点击效果 *\/\n        .main-btn:active, .func-btn:active {\n            transform: translateY(0);\n        }\n        \n        \/* 长页码时的特殊样式 *\/\n        .long-page .main-btn {\n            font-size: 11px;\n            padding: 3px 1px;\n        }\n        \n        .book {\n            width: 100%;\n            display: flex;\n            flex-direction: column;\n            align-items: flex-start;\n            margin-bottom: 8px;\n        }\n        .bookdes {\n            display: flex;\n            flex-direction: row;\n            margin: 5px;\n            width: 100%;\n            position: relative;\n            align-items: center;\n        }\n        .pic {\n            width: 25vw;\n            margin-right: 20px;\n            align-self: center;\n        }\n        .details {\n            width: 72vw;\n            margin-left: 20px;\n            align-self: center;\n            margin-left: auto;\n        }\n        .pic img {\n            border: 1px solid #C4C4C4;\n            border-radius: 5px;\n            box-shadow: 1px 2px 2px black;\n            width: 97%;\n            height: auto;\n        }\n        .name { font-size: 20px; color: #000; }\n        .author {\n            font-size: 15px;\n            display: inline-block;\n            position: absolute;\n            right: 8px;\n        }\n        .tag { font-size: 12px; margin-top: -10px; }\n        #loading {\n            background: rgba(0,0,0,0.1);\n            \n            margin: 10px 0;\n        }\n    `;\n    document.head.appendChild(style);\n}\n\n",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "",
    "shouldOverrideUrlLoading": "if(\/[\\?#&]book[AN]\/.test(url)){\n\ttitle = url.match(\/[\\?#&]book[AN].+?=(.*)\/)[1];\n\tURLDecoder = Packages.java.net.URLDecoder;\n\tgb2312Str = URLDecoder.decode(title,\"gbk\");\n utf8Str = URLDecoder.decode(title,\"utf-8\");\n\t result = gb2312Str.length() >= utf8Str.length();\n\t title = result?decodeURI(title):gb2312Str;\n\t java.searchBook(title);\n\t result = true\n\t}",
    "singleUrl": true,
    "sourceComment": "❗️保存标签,请按照以下格式放在【源URL】:\n\nhttps:\/\/m.jjwxc.net\/assort#标签1@生成的标签#标签2@生成的标签#标签3@生成的标签#\n\n\n❗️注意开头的https:\/\/m.jjwxc.net\/assort#不要删除,还有末尾的#也不要删除,每个标签分隔是用#。\n\n\n下面是完整【源URL】案例\n\nhttps:\/\/m.jjwxc.net\/assort#百合强强并重生@MTksNzUmcmVtb3ZldGFncz0mbm90bGlrZWNvbGxlY3Rpb25UeXBlcz1vcnMmZnc9MCZ5Yz0wJnh4PTMmc2Q9MCZseD0wJm1haW52aWV3PTAmZmJzaj0wJm5vdmVsYmVmYXZvcml0ZWRjb3VudD0wJmlzZmluaXNoPSZjb2xsZWN0aW9uVHlwZXM9YW5kcyZzZWFyY2hrZXlXb3Jkcz0=#百合甜爽穿@MTI0LDEzNywxMzQmcmVtb3ZldGFncz0mbm90bGlrZWNvbGxlY3Rpb25UeXBlcz1vcnMmZnc9MCZ5Yz0wJnh4PTMmc2Q9MCZseD0wJm1haW52aWV3PTAmZmJzaj0wJm5vdmVsYmVmYXZvcml0ZWRjb3VudD0wJmlzZmluaXNoPSZjb2xsZWN0aW9uVHlwZXM9b3JzJnNlYXJjaGtleVdvcmRzPQ==#",
    "sourceGroup": "阅读",
    "sourceIcon": "https:\/\/m-static.jjwxc.net\/images\/wap\/logo.png",
    "sourceName": " 📖\n精确搜索",
    "sourceUrl": "https:\/\/m.jjwxc.net\/assort#",
    "style": ""
}
广告