18AV

https://mjv006.com

分享者: laizhiyu (6509)发布时间: 1天前

也是根据洛亚橙大佬18AV订阅源修复而来。
开始使用先登录,点获取网址,右上角√返回会自动写入。
测试软件:legadoTeam,sigma其他款自测

AI修复,白嫖的TOKEN,用力蹬,用完就不蹬了
二维码导入
{
    "articleStyle": 3,
    "cacheFirst": false,
    "contentBlacklist": ".*(?:pemsrv.com|mmfree3.com|magsrv.com).*,.*adcg.*gif",
    "customOrder": 49,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "@js:\n(()=>{\nlet headerss=gethd();\nheaderss['User-Agent']=java.getWebViewUA();\n return JSON.stringify(headerss);\n})();",
    "injectJs": "if (window.local) {\n        function copyText(button, weizi) {\nconst text = weizi == 'before' ?\nbutton.previousElementSibling.textContent :\nweizi == 'after' ? button.nextElementSibling.textContent :\n'异常';\n    const btext = button.textContent;\n    navigator.clipboard.writeText(text)\n        .then(() => {\n            button.textContent = \"✓已复制\";\n            setTimeout(() => {\n                button.textContent = btext;\n            }, 1500);\n        })\n        .catch(err => {\n            button.textContent = \"✗失败\";\n            setTimeout(() => {\n                button.textContent = btext;\n            }, 1500);\n        });\n}\n\nlet pressTimer = null;\ndocument.querySelector('.jianjie').addEventListener('touchstart', (e) => {\n\tlet ee=e.target;\n\tif (ee.tagName=='A')\n\tpressTimer = setTimeout(() => {\n\t\tlet txt=ee.textContent+\"::\"+ee.href;\nnavigator.clipboard.writeText(txt).then(()=>{\n\t\/\/showToast(\"已复制到剪贴板,可填入登录界面自定义分类。<br>\"+txt, 1600);\n    java.longToast(\"已复制,可填入登录界面自定义分类。\\n\"+txt);\n\t});\n}, 1200);\n});\n  \ndocument.querySelector('.jianjie').addEventListener('touchend', e => {\n\tif (pressTimer) {\n\t\tclearTimeout(pressTimer);\n\t\tpressTimer = null;}\n});\n\ndocument.querySelector('.jianjie').addEventListener('click', e => {\n\tlet ee=event.target.closest('a');\n\tif (ee) {\n\t\te.preventDefault();\n\t\tlet url=ee.href;\n\t\tlet tt=ee.textContent;\n\t\tif (!tt) {\n\t\t\tlet a=ee.nextElementSibling.querySelector('a');\n\t\t\tif (a) tt=a.textContent;\n\t\t\t}\n            url = url.replace(\/[^\\\/].html\/,'');\n\t\tjava.open(\"sort\",JSON.stringify({[tt]:`data:;base64,{{java.base64Encode(\"${url}\"+page+\".html\")}},{\"type\":\"18av\"}`}));\n\t\t}\n});\n\ndocument.querySelector('.posts').addEventListener('click', e => {\n\tlet ee=event.target.closest('a');\n\tif (ee) {\n\t\te.preventDefault();\n\t\tlet tt=ee.innerText;\n\t\tif (!tt) {\n\t\t\tlet h3=ee.parentElement.nextElementSibling.querySelector('h3');\n\t\t\tif (h3) tt=h3.textContent;\n\t\t\t}\n       let bs64=java.base64Encode(ee.href.replace(\/^http.{4}[^\\\/]+\/,''));\njava.open(\"rss\",`${ee.href}@js:\n'data:;base64,${bs64},{\"type\":\"18av\"}'\n`,tt);\n\t\t}\n});\n\n}",
    "jsLib": "banben=\"1.1.7\";\nsleep=Packages.java.lang.Thread.sleep;\nu_a = 'Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/135.0.0.0 Safari\/537.36 Edg\/135.0.0.0';\nx_r_w = ''; \/\/com.microsoft.emmx\ns_c_u_p = `\"Windows\"`;\ns_c_u = `\"Microsoft Edge\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"`;\na_l = 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7';\n\nfunction gethd(url='',ck='') {\n\tlet ck0 = this.source.getLoginHeader()||'';\n\tlet headerss = {\n\t\t  \t'User-Agent': u_a,\n\t\t  \t'Cookie': ck0,\n\t\t  \t'x-requested-with': x_r_w,\n     \t'Accept-Language': a_l\n    \t }\nif (ck==1&&url!='') return url+','+JSON.stringify({'headers':headerss,'webView':true});\nif (ck!='') headerss['Cookie']=ck;\nif (url=='') return headerss;\nreturn url+','+JSON.stringify({'headers':headerss});\n}\n\nfunction uinfo() {\n\tlet m = null;\n\ttry {\n\t\tlet src = (typeof source !== 'undefined' && source) ? source : this.source;\n\t\tm = src.getLoginInfoMap();\n\t} catch (e) { m = null; }\n\treturn (m && typeof m === 'object') ? m : {};\n}\n\nfunction gets(x, r) {\nreturn r == undefined ? String(this.java.getString(x)) : String(this.java.getString(x,r));}\n\nfunction surl() {\n\tlet surl=uinfo()['网址']+'';\n\tif (!surl||surl=='undefined') surl='https:\/\/mjv006.com';\n\treturn surl.replace(\/\\\/$\/,'');}\n\nfunction tkey() {\n\tlet tkey = uinfo()['每日更新日期']+[];\n\tif (tkey&&tkey!='undefined') {\n\t\ttkey = tkey.replace(\/^\\d{0,2}(\\d{2})\\D(\\d{1,2})\\D(\\d{1,2})$\/, (mt, p1, p2, p3)=>{\n\t\t\tp1='20'+p1;\n\t\t\tp2=p2.padStart(2, '0');\n\t\t\tp3=p3.padStart(2, '0');\n\t\t\tp2>12&&(p2='012')\n\t\t\tp3>31&&(p3='031')\n\t\t\treturn p1+'-'+p2+'-'+p3;\n\t\t\t});\n\t\t\tif (!\/^\\d{4}-\\d{2}-\\d{2}$\/.test(tkey)) {\n\t\t\t\ttkey='';\n\t\t\t\tthis.java.toast('\\n❎请输入正确的时间格式');}\n}\nif (!tkey||tkey=='undefined') {tkey = this.java.timeFormatUTC(Date.now(),\"yyyy-MM-dd\",6*60*60*1000)+[];}\n\treturn tkey;}\n\t\nfunction rrcheck(url, webr) {\n\tconst {java, source, cookie} = this;\n\tlet webr2 = org.jsoup.Jsoup.parse(webr);\n\tlet url19 = (webr2.select('#fwin_dialog_submit').attr('onclick')+'').match(\/http[^\"']+\/);\nif (url19) {\n\tlet ck=java.connect(url19)\n\t.headers()\n\t.values(\"Set-Cookie\");\n\tlet cks = [];\n\tfor (let char of ck) {\n\tchar=(char+'').replace(\/;.+\/,'');\n\tcks.push(char);}\n\tck=cks.join('; '); \/\/带ajax得到的会话ck访问时不会有ck返回,为激活ck(主要用于不启用jar)\nck=ck||cookie.getCookie(url)+'';\n\/\/勾选ckjar就能getck读取本次软件会话ck(重启软件失效),setck函数才会一直保存源ck\nif (ck=='')\nck=source.getLoginHeader(); \/\/获取现有ck\nelse\nsource.putLoginHeader(ck); \/\/保存新ck\ncookie.setWebCookie(url,ck); \/\/同步ck到内置浏览器\n\tsleep(120); \/\/服务器记录可能需要延时\n\twebr=java.ajax(url); \/\/访问前会执行一次请求头规则\n\t}\n\treturn java.t2s(webr)+'';\n}\n\n\nfunction gengxin(){\nconst {java, source} = this;\n\tlet url0='https:\/\/gitee.com\/lyc486\/yuedu2\/commits\/main\/订阅\/18AV\/18av_特供版.json?browser_history=0&page=1&per=3';\n\tlet rr0=java.get(url0,{'User-Agent': 'Mozilla\/5.0 (Linux; Android 14)','X-Requested-With': 'XMLHttpRequest'}).body();\n\tlet gxlrr = com.jayway.jsonpath.JsonPath.read(rr0, '$.list[0:3].title');\n\tlet [gxlr, gxlr2, gxlr3] = gxlrr;\n\tgxlr=String(gxlr).split(\/^([^\\-]+)-\/);\n\tgxlr[0]=='' ? '' : gxlr=['','0',gxlr[0]];\n\tlet gxts;\n\tif (gxlr[1]>banben){gxts=['更新','0,140,186'];}\n\telse {gxts= ['导入','76,175,80'];};\n\tlet htm = `<html><head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>18AV ${gxts[0]}<\/title>\n<style>\ntable {\n\ttext-align: center;\n\tmargin: 0 auto;\n\t}\n.ann {\n\tdisplay: flex;\n\tjustify-content: center;\n\talign-items: center;\n\theight: 50vh;\n\t}\nbutton {\n\tbackground-color: rgb(${gxts[1]});\n\tcolor: white;\n\tborder: none;\n\tborder-radius: 4px;\n\theight: 6vh;\n\twidth: 30vw;\n\toverflow: hidden;\n\t}\nbutton span {\n  cursor: pointer;\n  display: inline-block;\n  position: relative;\n  transition: 0.4s;\n}\nbutton span:after {\n  content: '>';\n  position: absolute;\n  opacity: 0;\n  top: 0;\n  right: 30px;\n  transition: 0.2s;\n}\nbutton:active span {\n  padding-right: 20px;\n}\nbutton:active span:after {\n  opacity: 1;\n  right: -40px;\n}\n<\/style><\/head>\n<body>\n<table border=\"1\" cellspacing=\"0\">\n<th colspan=\"2\">最新日志:${gxlr[2]}<\/th>\n<tr><td>仓库版本:${gxlr[1]}<\/td>\n<td>本地版本:${banben}<\/td><\/tr>\n<tr>\n<td colspan=\"2\" style=\"text-align: left;\">往期日志:${gxlr2}<br>     ${gxlr3}<\/td>\n<\/tr>\n<\/table>\n<div class=\"ann\">\n<a href=\"legado:\/\/import\/importonline?src=https:\/\/gitee.com\/lyc486\/yuedu2\/raw\/main\/订阅\/18AV\/18av_特供版.json\"><button><span>${gxts[0]}<\/span><\/button><\/a>\n<\/div>\n<a href=\"legado:\/\/import\/importonline?src=https:\/\/cdn.jsdelivr.net\/gh\/Luoyacheng\/yuedu@main\/订阅\/18AV\/18av_特供版.json\" style=\"font-size: 10px;\">备用链接<\/a>\n<\/body>\n<\/html>`;\njava.startBrowser(`data:text\/html;base64,${java.base64Encode(htm)}`,'订阅源更新');\r\n}\n\nvar toastjs=`const toastStyle = document.createElement('style');\ntoastStyle.textContent = \".toast-container {position: fixed; z-index: 1000; pointer-events: none; display: flex; flex-direction: column; align-items: center;} .toast-container.top-center { top: 20px; left: 50%; transform: translateX(-50%); } .toast-container.top-left { top: 20px; left: 20px; } .toast-container.top-right { top: 20px; right: 20px; } .toast-container.bottom-center { bottom: 20px; left: 50%; transform: translateX(-50%); } .toast-container.bottom-left { bottom: 20px; left: 20px; } .toast-container.bottom-right { bottom: 20px; right: 20px; } .toast {background: rgba(0, 0, 0, 0.8); color: white; padding: 12px 14px; border-radius: 4px; margin-bottom: 10px;  word-break: initial; max-width: 80vw; opacity: 0; transform: translateY(20px); transition: opacity 0.3s, transform 0.3s; pointer-events: none;} .toast.show {opacity: 1; transform: translateY(0);} .toast.success {background: rgba(46, 204, 113, 0.9);} .toast.error {background: rgba(231, 76, 60, 0.9);} .toast.warning {background: rgba(241, 196, 15, 0.9);} .toast.info {background: rgba(52, 152, 219, 0.9);}\";\ndocument.head.appendChild(toastStyle);\nwindow.showToast = function (message, duration = 3000, type = 'default', position = 'bottom-center') {\n  let container = document.querySelector('.toast-container');\n  if (!container) {\n    container = document.createElement('div');\n    container.className = 'toast-container';\n    document.body.appendChild(container);\n  }\n  container.className = \"toast-container \" + position;\n  const toast = document.createElement('div');\n  toast.className = \"toast \" + type;\n  toast.innerHTML = message;\n  container.appendChild(toast);\n  setTimeout(() => {\n    toast.classList.add('show');\n  }, 10);\n  setTimeout(() => {\n    toast.classList.remove('show');\n    setTimeout(() => {\n      if (toast.parentNode) {\n        toast.parentNode.removeChild(toast);\n      }\n    }, 300);\n  }, duration);\n}`;\n\n\/* ================= [自定义分类 · 修复块] ================= *\/\n\/* 说明:本块会同时注入 jsLib 与 loginUrl。\n   - 放在末尾,同名函数后定义覆盖先定义,因此无需改动原有 uinfo()。\n   - sortUrl 环境只加载 jsLib;登录按钮环境只加载 loginUrl,两边都放一份才都有。 *\/\nvar FKEY_UIKEYS = ['网址', '每日更新日期', '继续播放', '自动播放', '显示链接', '预览截图', '随机主题', '启动页', '滑动等级', '播放器', '双击⏭️时间', '长按⏩倍速', '自定义分类'];\nvar FKEY_NAME = '自定义分类';\n\nfunction _fkSrc() {\n    try { if (typeof source !== 'undefined' && source) return source; } catch (e) {}\n    try { if (this && this.source) return this.source; } catch (e2) {}\n    return null;\n}\n\n\/* 判断一行是否为「key=value」的新字段。\n   难点:分类网址常带查询参数(?t=1),朴素的 indexOf('=') 会把续行误判成新字段,\n   导致已填的分类整段丢失。这里只在「= 左边确实像字段名」时才认定是新字段。 *\/\nfunction _fkIsKey(line) {\n    var i = line.indexOf('=');\n    if (i <= 0) return null;\n    var k = line.substring(0, i);\n    if (FKEY_UIKEYS.indexOf(k) > -1) return k;\n    if (k.indexOf('\/') > -1 || k.indexOf('::') > -1 || k.indexOf(':') > -1) return null;\n    if (k.indexOf('?') > -1 || k.indexOf('&') > -1 || k.indexOf('.') > -1) return null;\n    if (\/[\\s\"'`<>\\[\\]{}|\\\\^]\/.test(k)) return null;\n    if (k.length > 12) return null;\n    return k;\n}\n\n\/* 直接解析 loginInfo 原始串,能还原被 getLoginInfoMap() 截断的多行值 *\/\nfunction _fkRawMap() {\n    var m = {};\n    var src = _fkSrc();\n    if (!src) return m;\n    var raw = '';\n    try { raw = src.getLoginInfo() + ''; } catch (e) { raw = ''; }\n    if (!raw || raw == 'null' || raw == 'undefined') return m;\n    var lines = String(raw).split(\/[\\r\\n]+\/);\n    var cur = null;\n    for (var i = 0; i < lines.length; i++) {\n        var line = lines[i];\n        if (!line.length) continue;\n        var k = _fkIsKey(line);\n        if (k) {\n            cur = k;\n            m[cur] = line.substring(line.indexOf('=') + 1);\n        } else if (cur) {\n            m[cur] = m[cur] + '\\n' + line;\n        }\n    }\n    return m;\n}\n\n\/* 覆盖原 uinfo():Map 结果 + 原始串补全,两者取更完整的那份 *\/\nfunction uinfo() {\n    var m = {};\n    var src = _fkSrc();\n    if (src) {\n        var mm = null;\n        try { mm = src.getLoginInfoMap(); } catch (e) { mm = null; }\n        if (mm) {\n            var got = false;\n            try {\n                var it = mm.keySet().iterator();\n                while (it.hasNext()) {\n                    var k = it.next() + '';\n                    if (_fkBadKey(k)) continue;                  \/\/ 丢掉分类碎片\n                    var v = mm.get(k);\n                    m[k] = (v === null || v === undefined) ? '' : (v + '');\n                }\n                got = true;\n            } catch (e2) { got = false; }\n            if (!got) {\n                try {\n                    for (var kk in mm) {\n                        if (kk == 'class' || kk == 'empty') continue;\n                        if (_fkBadKey(kk)) continue;\n                        m[kk] = mm[kk] + '';\n                    }\n                } catch (e3) {}\n            }\n        }\n    }\n    var rm = {};\n    try { rm = _fkRawMap(); } catch (e4) { rm = {}; }\n    for (var k2 in rm) {\n        if (!Object.prototype.hasOwnProperty.call(rm, k2)) continue;\n        var nv = rm[k2] + '';\n        var ov = (m[k2] === undefined ? '' : m[k2] + '');\n        if (nv && (!ov || nv.length > ov.length)) m[k2] = nv;\n    }\n    return m;\n}\n\nfunction _fkVal(v) {\n    v = (v === undefined || v === null) ? '' : (v + '');\n    return (v == 'undefined' || v == 'null') ? '' : v;\n}\n\n\/* ArtPlayer 版本号:同步拉取 unpkg。\n   原写法把它内联在 loginUi 里,一旦网络不可达就抛异常,导致整个登录界面渲染失败(0 控件)。\n   这里包了 try\/catch,失败返回 '?'。 *\/\nfunction apver() {\n    try {\n        var s = java.importScript('https:\/\/unpkg.com\/artplayer\/dist\/artplayer.js');\n        var v = s && String(s).match(\/artplayer\\.js.*v([0-9][^\\s\"']*)\/i);\n        return v ? v[1] : '?';\n    } catch (e) { return '?'; }\n}\n\n\/* 判断是否为「分类碎片」key。\n   分类网址里带 ?t=1 时,legado 的 getLoginInfoMap() 会把整行当成新字段存进来\n   (key = \"演员A::https:\/\/...?t\")。这些碎片必须剔除,否则回写 loginInfo 时会污染数据。 *\/\nfunction _fkBadKey(k) {\n    k = String(k || '');\n    if (!k) return true;\n    if (FKEY_UIKEYS.indexOf(k) > -1) return false;\n    if (k.indexOf('::') > -1) return true;\n    if (k.indexOf('\/') > -1) return true;\n    if (k.indexOf('?') > -1 || k.indexOf('&') > -1) return true;\n    if (k.indexOf('.') > -1) return true;\n    if (k.indexOf('=') > -1) return true;\n    return false;\n}\n\n\/* 读「自定义分类」原文:loginInfo 与源变量 fkey 两路,取「能解析出更多条目」的那份。\n   注意不能简单取更长的——归一化后两条内容常常重复,取更长会得到重复来源。 *\/\nfunction fkeyRaw() {\n    var a = '';\n    try { a = _fkVal(uinfo()[FKEY_NAME]); } catch (e) { a = ''; }\n    var b = '';\n    var src = _fkSrc();\n    if (src) { try { b = _fkVal(src.get('fkey')); } catch (e2) { b = ''; } }\n    if (!String(a).trim()) return b;\n    if (!String(b).trim()) return a;\n    try { return (fkeyCount(b) > fkeyCount(a)) ? b : a; } catch (e3) { return a; }\n}\n\n\/* 归一化成「单条一行、用 ; 分隔」的单行串 *\/\nfunction fkeyNorm(raw) {\n    raw = (raw || '') + '';\n    if (raw == 'undefined' || raw == 'null') raw = '';\n    if (!String(raw).trim()) return '';\n    var items = String(raw).split(\/[\\r\\n,,;;|]+\/);\n    var out = [];\n    for (var i = 0; i < items.length; i++) {\n        var t = String(items[i] || '').replace(\/^[\\s\"'“”`]+|[\\s\"'“”`]+$\/g, '');\n        if (t) out.push(t);\n    }\n    if (out.length < 2 && \/\\s\/.test(raw)) {\n        var t2 = String(raw).trim().split(\/\\s+\/);\n        var o2 = [];\n        for (var j = 0; j < t2.length; j++) if (t2[j]) o2.push(t2[j]);\n        if (o2.length > out.length) out = o2;\n    }\n    return out.join(';');\n}\n\nfunction _fkNameOf(url, i) {\n    var seg = String(url).replace(\/\\\/+$\/, '').split('\/').pop();\n    if (!seg || \/^(?:page|\\d+)(?:\\.html)?$\/i.test(seg)) {\n        var tmp = String(url).replace(\/\\\/+$\/, '').split('\/');\n        seg = tmp.length > 1 ? tmp[tmp.length - 2] : '';\n    }\n    seg = String(seg || '').replace(\/\\.html$\/i, '');\n    try { seg = decodeURIComponent(seg); } catch (e) {}\n    return seg || ('分类' + (i + 1));\n}\n\n\/* 把原始文本切成条目列表(不生成最终 URL) *\/\nfunction fkeyItems(raw) {\n    raw = (raw || '') + '';\n    if (raw == 'undefined' || raw == 'null') raw = '';\n    if (!String(raw).trim()) return [];\n    var items = String(raw).split(\/[\\r\\n,,;;|]+\/);\n    var list = [];\n    for (var i = 0; i < items.length; i++) {\n        var t = String(items[i] || '').replace(\/^[\\s\"'“”`]+|[\\s\"'“”`]+$\/g, '');\n        if (t) list.push(t);\n    }\n    if (list.length < 2 && \/\\s\/.test(raw)) {\n        var t2 = String(raw).trim().split(\/\\s+\/);\n        var l2 = [];\n        for (var j = 0; j < t2.length; j++) if (t2[j]) l2.push(t2[j]);\n        if (l2.length > list.length) list = l2;\n    }\n    var out = [];\n    for (var n = 0; n < list.length; n++) {\n        var item = list[n];\n        var name = '', url = '';\n        var p = item.indexOf('::');\n        if (p > -1) { name = item.substring(0, p).trim(); url = item.substring(p + 2).trim(); }\n        else { url = item; }\n        if (!\/[\\\/\\.]\/.test(url)) continue;                       \/\/ 纯文字碎片,丢弃\n        url = url.replace(\/^\\s*(?:https?:)?\\\/\\\/[^\\\/]+\/i, '').replace(\/\\s+\/g, '');\n        if (!url) continue;\n        if (url.charAt(0) != '\/') url = '\/' + url;\n        var q = '';\n        var qi = url.indexOf('?');\n        if (qi > -1) { q = url.substring(qi + 1); url = url.substring(0, qi); }\n        if (!name) name = _fkNameOf(url, n);\n        name = String(name).replace(\/[::\\r\\n]\/g, '').trim() || ('分类' + (n + 1));\n        out.push({ name: name, url: url, q: q });\n    }\n    return out;\n}\n\n\/* 条目 → sortUrl 行 *\/\nfunction fkeyRow(it) {\n    var url = it.url, q = it.q, body;\n    if (\/\\\/page\\.html$\/i.test(url) || \/\\\/\\d+\\.html$\/i.test(url)) {\n        body = '\"' + url.replace(\/\\\/(?:page|\\d+)\\.html$\/i, '\/') + '\"+page+\".html\"';\n    } else if (\/\\\/index\\.html$\/i.test(url)) {\n        body = '\"' + url + '?t=\"+page';\n    } else if (\/\\.html$\/i.test(url)) {\n        body = '\"' + url + '\"';                                  \/\/ 日期页\/固定页:单页\n    } else if (\/(?:^|&)t=\/.test(q)) {\n        body = '\"' + url + '?t=\"+page';\n    } else if (\/\\\/$\/.test(url)) {\n        body = '\"' + url + '\"+page+\".html\"';\n    } else {\n        body = '\"' + url + '\/\"+page+\".html\"';\n    }\n    return it.name + '::data:;base64,{{java.base64Encode(' + body + ')}},{\"type\":\"18av\"}';\n}\n\nfunction fkeyFrom(raw) {\n    var items = fkeyItems(raw), out = [];\n    for (var i = 0; i < items.length; i++) out.push(fkeyRow(items[i]));\n    return out;\n}\n\nfunction fkeyCount(raw) {\n    try { return fkeyItems(raw).length; } catch (e) { return 0; }\n}\n\n\/* 解析成 sortUrl 行数组(sortUrl 与按钮都调它) *\/\nfunction fkey() {\n    try { return fkeyFrom(fkeyRaw()); } catch (e) { return []; }\n}\n\n\/* 归一化 + 双写(源变量 fkey)。登录时会自动跑一次 *\/\nfunction normFkey() {\n    var raw = fkeyRaw();\n    if (!String(raw).trim()) return 0;\n    var single = fkeyNorm(raw);\n    if (!single) return 0;\n    var n = fkeyCount(single);\n    var src = _fkSrc();\n    if (!src) return n;\n    try { src.put('fkey', single); } catch (e) {}\n    if (raw.indexOf('\\n') < 0 && raw === single) return n;   \/\/ 已是单行,不冒险改 loginInfo\n    var raw0 = '';\n    try { raw0 = src.getLoginInfo() + ''; } catch (e2) { raw0 = ''; }\n    if (!raw0 || raw0 == 'null' || raw0 == 'undefined') return n;\n    try {\n        var m = uinfo();\n        var clean = {};\n        for (var k in m) {\n            if (!Object.prototype.hasOwnProperty.call(m, k)) continue;\n            if (FKEY_UIKEYS.indexOf(k) < 0) continue;            \/\/ 只写真正的 UI 字段\n            clean[k] = m[k];\n        }\n        clean[FKEY_NAME] = single;\n        src.putLoginInfo(JSON.stringify(clean));\n        \/\/ 校验只看 loginInfo 本身(不能用 uinfo(),它会被源变量兜底而掩盖失败)\n        var back = '';\n        try { back = _fkVal(_fkRawMap()[FKEY_NAME]); } catch (e3) {}\n        if (back.indexOf(fkeyItems(single)[0].name) < 0 && back.indexOf(single.split(';')[0]) < 0) {\n            try { src.putLoginInfo(raw0); } catch (e4) {}    \/\/ 回写失败则还原\n        }\n    } catch (e5) {}\n    return n;\n}\n\n\/* 诊断:把真实读到的一切弹出来,便于定位 *\/\nfunction diagFkey() {\n    var L = [];\n    var src = _fkSrc();\n    L.push('① source 对象:' + (src ? '可用' : '不可用'));\n    var rawInfo = '(读不到)';\n    try { rawInfo = src ? (src.getLoginInfo() + '') : '(无 source)'; } catch (e) { rawInfo = 'getLoginInfo() 异常: ' + e; }\n    L.push('② loginInfo 原始串(前400字):\\n' + String(rawInfo).substring(0, 400));\n    var keys = [];\n    try { var mm = uinfo(); for (var k in mm) if (Object.prototype.hasOwnProperty.call(mm, k)) keys.push(k); } catch (e2) {}\n    L.push('③ 解析到字段(' + keys.length + '):' + keys.join(' \/ '));\n    var v = fkeyRaw();\n    L.push('④ 自定义分类 原文(前300字):\\n' + (String(v).trim() ? String(v).substring(0, 300) : '(空)'));\n    var sv = '(空)';\n    try { sv = src ? _fkVal(src.get('fkey')) : '(无 source)'; } catch (e3) {}\n    L.push('⑤ 源变量 fkey(前300字):\\n' + (String(sv).trim() ? String(sv).substring(0, 300) : '(空)'));\n    var arr = [];\n    var err = '';\n    try { arr = fkey(); } catch (e4) { err = e4 + ''; }\n    if (err) L.push('⑥ 解析异常:' + err);\n    else if (!arr.length) L.push('⑥ 解析结果:0 个(没识别出有效条目)');\n    else {\n        var names = [];\n        for (var i = 0; i < arr.length; i++) names.push('  ' + (i + 1) + '. ' + arr[i].split('::')[0]);\n        L.push('⑥ 解析结果:' + arr.length + ' 个\\n' + names.join('\\n'));\n    }\n    var txt = '🔧 自定义分类诊断\\n\\n' + L.join('\\n\\n');\n    try { java.setClipboard(txt); } catch (e5) {}\n    try { java.longToast('\\n' + txt + '\\n\\n(已复制到剪贴板)'); } catch (e6) {}\n    return txt;\n}\n\n\/* 校验:告诉用户当前识别到什么 *\/\nfunction checkFkey() {\n    var raw = fkeyRaw();\n    var tip;\n    if (!String(raw).trim()) {\n        tip = '❎ 没读到分类内容。\\n\\n'\n            + '请按下面顺序操作:\\n'\n            + '1) 在上面的「自定义分类」框里填内容\\n'\n            + '2) 点右上角 √ 保存(很关键,不保存读不到)\\n'\n            + '3) 再回到本页点「🧪校验分类」\\n\\n'\n            + '【格式】每行一个:\\n分类名::网址\\n\\n'\n            + '多个分类用 换行 \/ 分号 \/ 逗号 隔开都行。\\n'\n            + '在视频详情页长按简介里的分类或演员名,会自动复制成「名称::网址」。\\n\\n'\n            + '还是不行就点右边的「🔧诊断」把结果发我。';\n    } else {\n        var arr = [];\n        var err = '';\n        try { arr = fkey(); } catch (e) { err = e + ''; }\n        if (err) tip = '❎ 解析出错:' + err;\n        else if (!arr.length) tip = '❎ 读到了内容,但没识别出有效条目:\\n' + String(raw).substring(0, 300)\n            + '\\n\\n每条要像这样:分类名::https:\/\/mjv006.com\/zh\/xxx\/';\n        else {\n            var names = [];\n            for (var i = 0; i < arr.length; i++) names.push('  ' + (i + 1) + '. ' + arr[i].split('::')[0]);\n            tip = '✅ 已识别 ' + arr.length + ' 个分类:\\n\\n' + names.join('\\n')\n                + '\\n\\n返回后发现页生效(需重新进发现页)。';\n        }\n    }\n    java.longToast('\\n' + tip);\n}\n\n\/* 备份:写入源变量,避免 loginInfo 读取异常时丢失 *\/\nfunction saveFkey() {\n    var n = 0;\n    try { n = normFkey(); } catch (e) {}\n    if (!n) { try { n = fkeyCount(fkeyRaw()); } catch (e0) {} }\n    var raw = fkeyRaw();\n    if (!String(raw).trim()) {\n        java.longToast('\\n❎ 读到的内容为空。\\n请先填写 → 点右上角 √ 保存 → 再进本页点备份。\\n\\n若已保存仍读不到,点「🔧诊断」看原因。');\n        return;\n    }\n    java.longToast('\\n✅ 已备份 ' + n + ' 条:\\n\\n' + String(raw).substring(0, 300)\n        + '\\n\\n备份内容存在源变量 fkey 里,即使登录信息丢失也能恢复。');\n}\n\n\/* 清空备份 *\/\nfunction clearFkey() {\n    var src = _fkSrc();\n    try { if (src) src.put('fkey', ''); } catch (e) {}\n    java.longToast('\\n✅ 已清空备份的自定义分类。\\n(发现页会只剩内置分类,登录框里的内容不受影响)');\n}\n\/* =============== [自定义分类 · 修复块 end] =============== *\/\n",
    "lastUpdateTime": 1788075530188,
    "loadWithBaseUrl": true,
    "loginUi": "@js:\n`[\n    {\n        name: \"网址\",\n        type: \"text\"\n    },\n    {\n        name: \"每日更新日期\",\n        type: \"text\"\n    },\n    \t{\n        name: \"ArtPlayer\",\n        viewName: \"'ArtPlayer V'+apver()\",\n        type: \"button\",\n        action: \"bfq()\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": true\n        }\n    },\n    \t{\n        name: \"订阅源版本 \",\n        viewName:\"'订阅源版本 V'+banben\",\n        type: \"button\",\n        action: \"gengxin()\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    \t{\n        name: \"继续播放\",\n        type: \"toggle\",\n        chars:[\"🔳\", \"✅\"],\n        default:\"✅\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": true,\n            \"layout_justifySelf\":\"right\"\n        }\n    },\n    \t{\n        name: \"自动播放\",\n        type: \"toggle\",\n        chars:[\"🔳\", \"✅\"],\n        default:\"🔳\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false,\n            \"layout_justifySelf\":\"right\"\n        }\n    },\n    \t{\n        name: \"显示链接\",\n        type: \"toggle\",\n        chars:[\"🔳\", \"✅\"],\n        default:\"✅\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false,\n            \"layout_justifySelf\":\"right\"\n        }\n    },\n    \t{\n        name: \"预览截图\",\n        type: \"toggle\",\n        chars:[\"🔳\", \"✅\"],\n        default:\"✅\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false,\n            \"layout_justifySelf\":\"right\"\n        }\n    },\n    \t{\n        name: \"随机主题\",\n        type: \"toggle\",\n        chars:[\"🔳\", \"✅\"],\n        default:\"✅\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false,\n            \"layout_justifySelf\":\"right\"\n        }\n    },\n    \t{\n        name: \"启动页\",\n        type: \"toggle\",\n        chars:[\"🔳\", \"✅\"],\n        default:\"✅\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false,\n            \"layout_justifySelf\":\"right\"\n        }\n    },\n    \t{\n        name: \"滑动等级\",\n        type: \"select\",\n        chars: [\"1️⃣\",\"2️⃣\",\"3️⃣\",\"4️⃣\",\"5️⃣\",\"6️⃣\",\"7️⃣\"],\n        default:\"3️⃣\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": true\n        }\n    },\n    \t{\n        name: \"播放器\",\n        type: \"select\",\n        chars:['默认','阅读','外部'],\n        default:\"默认\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    {\n        name: \"双击⏭️时间\",\n        type: \"select\",\n        chars:[5,10,15,20,30,45],\n        default: \"10\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    {\n        name: \"长按⏩倍速\",\n        type: \"select\",\n        chars:[1.5,2.0,2.5,3.0,3.5,4.0,5.0,6.0],\n        default: \"3.0\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    {\n        name: \"自定义分类\",\n        type: \"text\"\n    },\n    \t{\n        name: \"🧪校验分类\",\n        type: \"button\",\n        action: \"checkFkey()\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": true\n        }\n    },\n    \t{\n        name: \"💾备份分类\",\n        type: \"button\",\n        action: \"saveFkey()\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    \t{\n        name: \"🗑️清空备份\",\n        type: \"button\",\n        action: \"clearFkey()\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    \t{\n        name: \"🔧诊断\",\n        type: \"button\",\n        action: \"diagFkey()\",\n        style: {\n            \"layout_flexGrow\": 1,\n            \"layout_flexBasisPercent\": 0.4,\n            \"layout_wrapBefore\": false\n        }\n    },\n    \t{\n        name: \"🌐获取网址\",\n        type: \"button\",\n        action: \"fabuye()\",\n        style: {\n            \"layout_flexGrow\": 0,\n            \"layout_flexBasisPercent\": -1,\n            \"layout_wrapBefore\": true\n        }\n    }\n]`",
    "loginUrl": "function login() {\n    try { normFkey(); } catch (e) {}\n}\n\nfunction fabuye(){\n\tlet fbyu = source.get('fbyu')+'';\n\tlet headers = source.getHeaderMap(false);\n\ttry {java.head(fbyu,headers,6000);}\n\tcatch(e) {fbyu='https:\/\/mm18vd.com';}\n\tlet webr = java.startBrowserAwait(fbyu,'发布页',false).body();\n\tlet rr = org.jsoup.Jsoup.parse(webr);\n\tfbyu = rr.select('.list:nth-of-type(3) a').attr('href')+'';\n\tsource.put('fbyu',fbyu);\n\tlet surl = (rr.select('.list:nth-of-type(6) a').attr('href')+'').replace('http:\/\/','https:\/\/');\n\ttry {java.head(surl,headers,6000);\n\tjava.longToast('已填写最新网址\\n'+surl);\n\tlet Info={};\n\tInfo['网址'] = surl;\n    java.upLoginData(Info);\n} catch(e) {java.longToast('得到的网址\\n'+surl+'\\n无法访问,不进行记录');}\n}\n\nfunction bfq(){\njava.toast('\\n正在更新播放器...');\nvar bb='?';\ntry { java.deleteFile('dcc1a0ac99b90ead.js'); } catch(e0) {}\ntry {\n\tvar js = java.cacheFile('https:\/\/unpkg.com\/artplayer\/dist\/artplayer.js')+'';\n\tvar mv = js.match(\/artplayer\\.js.*v([0-9][^\\s\"']*)\/i);\n\tif (mv) bb = mv[1];\n} catch(e) { bb='?'; }\njava.longToast('\\n当前版本号:V'+bb+(bb=='?' ? '(获取失败,多为网络问题,不影响分类与播放)' : ''));\n\t}\n\n\/* ================= [自定义分类 · 修复块] ================= *\/\n\/* 说明:本块会同时注入 jsLib 与 loginUrl。\n   - 放在末尾,同名函数后定义覆盖先定义,因此无需改动原有 uinfo()。\n   - sortUrl 环境只加载 jsLib;登录按钮环境只加载 loginUrl,两边都放一份才都有。 *\/\nvar FKEY_UIKEYS = ['网址', '每日更新日期', '继续播放', '自动播放', '显示链接', '预览截图', '随机主题', '启动页', '滑动等级', '播放器', '双击⏭️时间', '长按⏩倍速', '自定义分类'];\nvar FKEY_NAME = '自定义分类';\n\nfunction _fkSrc() {\n    try { if (typeof source !== 'undefined' && source) return source; } catch (e) {}\n    try { if (this && this.source) return this.source; } catch (e2) {}\n    return null;\n}\n\n\/* 判断一行是否为「key=value」的新字段。\n   难点:分类网址常带查询参数(?t=1),朴素的 indexOf('=') 会把续行误判成新字段,\n   导致已填的分类整段丢失。这里只在「= 左边确实像字段名」时才认定是新字段。 *\/\nfunction _fkIsKey(line) {\n    var i = line.indexOf('=');\n    if (i <= 0) return null;\n    var k = line.substring(0, i);\n    if (FKEY_UIKEYS.indexOf(k) > -1) return k;\n    if (k.indexOf('\/') > -1 || k.indexOf('::') > -1 || k.indexOf(':') > -1) return null;\n    if (k.indexOf('?') > -1 || k.indexOf('&') > -1 || k.indexOf('.') > -1) return null;\n    if (\/[\\s\"'`<>\\[\\]{}|\\\\^]\/.test(k)) return null;\n    if (k.length > 12) return null;\n    return k;\n}\n\n\/* 直接解析 loginInfo 原始串,能还原被 getLoginInfoMap() 截断的多行值 *\/\nfunction _fkRawMap() {\n    var m = {};\n    var src = _fkSrc();\n    if (!src) return m;\n    var raw = '';\n    try { raw = src.getLoginInfo() + ''; } catch (e) { raw = ''; }\n    if (!raw || raw == 'null' || raw == 'undefined') return m;\n    var lines = String(raw).split(\/[\\r\\n]+\/);\n    var cur = null;\n    for (var i = 0; i < lines.length; i++) {\n        var line = lines[i];\n        if (!line.length) continue;\n        var k = _fkIsKey(line);\n        if (k) {\n            cur = k;\n            m[cur] = line.substring(line.indexOf('=') + 1);\n        } else if (cur) {\n            m[cur] = m[cur] + '\\n' + line;\n        }\n    }\n    return m;\n}\n\n\/* 覆盖原 uinfo():Map 结果 + 原始串补全,两者取更完整的那份 *\/\nfunction uinfo() {\n    var m = {};\n    var src = _fkSrc();\n    if (src) {\n        var mm = null;\n        try { mm = src.getLoginInfoMap(); } catch (e) { mm = null; }\n        if (mm) {\n            var got = false;\n            try {\n                var it = mm.keySet().iterator();\n                while (it.hasNext()) {\n                    var k = it.next() + '';\n                    if (_fkBadKey(k)) continue;                  \/\/ 丢掉分类碎片\n                    var v = mm.get(k);\n                    m[k] = (v === null || v === undefined) ? '' : (v + '');\n                }\n                got = true;\n            } catch (e2) { got = false; }\n            if (!got) {\n                try {\n                    for (var kk in mm) {\n                        if (kk == 'class' || kk == 'empty') continue;\n                        if (_fkBadKey(kk)) continue;\n                        m[kk] = mm[kk] + '';\n                    }\n                } catch (e3) {}\n            }\n        }\n    }\n    var rm = {};\n    try { rm = _fkRawMap(); } catch (e4) { rm = {}; }\n    for (var k2 in rm) {\n        if (!Object.prototype.hasOwnProperty.call(rm, k2)) continue;\n        var nv = rm[k2] + '';\n        var ov = (m[k2] === undefined ? '' : m[k2] + '');\n        if (nv && (!ov || nv.length > ov.length)) m[k2] = nv;\n    }\n    return m;\n}\n\nfunction _fkVal(v) {\n    v = (v === undefined || v === null) ? '' : (v + '');\n    return (v == 'undefined' || v == 'null') ? '' : v;\n}\n\n\/* ArtPlayer 版本号:同步拉取 unpkg。\n   原写法把它内联在 loginUi 里,一旦网络不可达就抛异常,导致整个登录界面渲染失败(0 控件)。\n   这里包了 try\/catch,失败返回 '?'。 *\/\nfunction apver() {\n    try {\n        var s = java.importScript('https:\/\/unpkg.com\/artplayer\/dist\/artplayer.js');\n        var v = s && String(s).match(\/artplayer\\.js.*v([0-9][^\\s\"']*)\/i);\n        return v ? v[1] : '?';\n    } catch (e) { return '?'; }\n}\n\n\/* 判断是否为「分类碎片」key。\n   分类网址里带 ?t=1 时,legado 的 getLoginInfoMap() 会把整行当成新字段存进来\n   (key = \"演员A::https:\/\/...?t\")。这些碎片必须剔除,否则回写 loginInfo 时会污染数据。 *\/\nfunction _fkBadKey(k) {\n    k = String(k || '');\n    if (!k) return true;\n    if (FKEY_UIKEYS.indexOf(k) > -1) return false;\n    if (k.indexOf('::') > -1) return true;\n    if (k.indexOf('\/') > -1) return true;\n    if (k.indexOf('?') > -1 || k.indexOf('&') > -1) return true;\n    if (k.indexOf('.') > -1) return true;\n    if (k.indexOf('=') > -1) return true;\n    return false;\n}\n\n\/* 读「自定义分类」原文:loginInfo 与源变量 fkey 两路,取「能解析出更多条目」的那份。\n   注意不能简单取更长的——归一化后两条内容常常重复,取更长会得到重复来源。 *\/\nfunction fkeyRaw() {\n    var a = '';\n    try { a = _fkVal(uinfo()[FKEY_NAME]); } catch (e) { a = ''; }\n    var b = '';\n    var src = _fkSrc();\n    if (src) { try { b = _fkVal(src.get('fkey')); } catch (e2) { b = ''; } }\n    if (!String(a).trim()) return b;\n    if (!String(b).trim()) return a;\n    try { return (fkeyCount(b) > fkeyCount(a)) ? b : a; } catch (e3) { return a; }\n}\n\n\/* 归一化成「单条一行、用 ; 分隔」的单行串 *\/\nfunction fkeyNorm(raw) {\n    raw = (raw || '') + '';\n    if (raw == 'undefined' || raw == 'null') raw = '';\n    if (!String(raw).trim()) return '';\n    var items = String(raw).split(\/[\\r\\n,,;;|]+\/);\n    var out = [];\n    for (var i = 0; i < items.length; i++) {\n        var t = String(items[i] || '').replace(\/^[\\s\"'“”`]+|[\\s\"'“”`]+$\/g, '');\n        if (t) out.push(t);\n    }\n    if (out.length < 2 && \/\\s\/.test(raw)) {\n        var t2 = String(raw).trim().split(\/\\s+\/);\n        var o2 = [];\n        for (var j = 0; j < t2.length; j++) if (t2[j]) o2.push(t2[j]);\n        if (o2.length > out.length) out = o2;\n    }\n    return out.join(';');\n}\n\nfunction _fkNameOf(url, i) {\n    var seg = String(url).replace(\/\\\/+$\/, '').split('\/').pop();\n    if (!seg || \/^(?:page|\\d+)(?:\\.html)?$\/i.test(seg)) {\n        var tmp = String(url).replace(\/\\\/+$\/, '').split('\/');\n        seg = tmp.length > 1 ? tmp[tmp.length - 2] : '';\n    }\n    seg = String(seg || '').replace(\/\\.html$\/i, '');\n    try { seg = decodeURIComponent(seg); } catch (e) {}\n    return seg || ('分类' + (i + 1));\n}\n\n\/* 把原始文本切成条目列表(不生成最终 URL) *\/\nfunction fkeyItems(raw) {\n    raw = (raw || '') + '';\n    if (raw == 'undefined' || raw == 'null') raw = '';\n    if (!String(raw).trim()) return [];\n    var items = String(raw).split(\/[\\r\\n,,;;|]+\/);\n    var list = [];\n    for (var i = 0; i < items.length; i++) {\n        var t = String(items[i] || '').replace(\/^[\\s\"'“”`]+|[\\s\"'“”`]+$\/g, '');\n        if (t) list.push(t);\n    }\n    if (list.length < 2 && \/\\s\/.test(raw)) {\n        var t2 = String(raw).trim().split(\/\\s+\/);\n        var l2 = [];\n        for (var j = 0; j < t2.length; j++) if (t2[j]) l2.push(t2[j]);\n        if (l2.length > list.length) list = l2;\n    }\n    var out = [];\n    for (var n = 0; n < list.length; n++) {\n        var item = list[n];\n        var name = '', url = '';\n        var p = item.indexOf('::');\n        if (p > -1) { name = item.substring(0, p).trim(); url = item.substring(p + 2).trim(); }\n        else { url = item; }\n        if (!\/[\\\/\\.]\/.test(url)) continue;                       \/\/ 纯文字碎片,丢弃\n        url = url.replace(\/^\\s*(?:https?:)?\\\/\\\/[^\\\/]+\/i, '').replace(\/\\s+\/g, '');\n        if (!url) continue;\n        if (url.charAt(0) != '\/') url = '\/' + url;\n        var q = '';\n        var qi = url.indexOf('?');\n        if (qi > -1) { q = url.substring(qi + 1); url = url.substring(0, qi); }\n        if (!name) name = _fkNameOf(url, n);\n        name = String(name).replace(\/[::\\r\\n]\/g, '').trim() || ('分类' + (n + 1));\n        out.push({ name: name, url: url, q: q });\n    }\n    return out;\n}\n\n\/* 条目 → sortUrl 行 *\/\nfunction fkeyRow(it) {\n    var url = it.url, q = it.q, body;\n    if (\/\\\/page\\.html$\/i.test(url) || \/\\\/\\d+\\.html$\/i.test(url)) {\n        body = '\"' + url.replace(\/\\\/(?:page|\\d+)\\.html$\/i, '\/') + '\"+page+\".html\"';\n    } else if (\/\\\/index\\.html$\/i.test(url)) {\n        body = '\"' + url + '?t=\"+page';\n    } else if (\/\\.html$\/i.test(url)) {\n        body = '\"' + url + '\"';                                  \/\/ 日期页\/固定页:单页\n    } else if (\/(?:^|&)t=\/.test(q)) {\n        body = '\"' + url + '?t=\"+page';\n    } else if (\/\\\/$\/.test(url)) {\n        body = '\"' + url + '\"+page+\".html\"';\n    } else {\n        body = '\"' + url + '\/\"+page+\".html\"';\n    }\n    return it.name + '::data:;base64,{{java.base64Encode(' + body + ')}},{\"type\":\"18av\"}';\n}\n\nfunction fkeyFrom(raw) {\n    var items = fkeyItems(raw), out = [];\n    for (var i = 0; i < items.length; i++) out.push(fkeyRow(items[i]));\n    return out;\n}\n\nfunction fkeyCount(raw) {\n    try { return fkeyItems(raw).length; } catch (e) { return 0; }\n}\n\n\/* 解析成 sortUrl 行数组(sortUrl 与按钮都调它) *\/\nfunction fkey() {\n    try { return fkeyFrom(fkeyRaw()); } catch (e) { return []; }\n}\n\n\/* 归一化 + 双写(源变量 fkey)。登录时会自动跑一次 *\/\nfunction normFkey() {\n    var raw = fkeyRaw();\n    if (!String(raw).trim()) return 0;\n    var single = fkeyNorm(raw);\n    if (!single) return 0;\n    var n = fkeyCount(single);\n    var src = _fkSrc();\n    if (!src) return n;\n    try { src.put('fkey', single); } catch (e) {}\n    if (raw.indexOf('\\n') < 0 && raw === single) return n;   \/\/ 已是单行,不冒险改 loginInfo\n    var raw0 = '';\n    try { raw0 = src.getLoginInfo() + ''; } catch (e2) { raw0 = ''; }\n    if (!raw0 || raw0 == 'null' || raw0 == 'undefined') return n;\n    try {\n        var m = uinfo();\n        var clean = {};\n        for (var k in m) {\n            if (!Object.prototype.hasOwnProperty.call(m, k)) continue;\n            if (FKEY_UIKEYS.indexOf(k) < 0) continue;            \/\/ 只写真正的 UI 字段\n            clean[k] = m[k];\n        }\n        clean[FKEY_NAME] = single;\n        src.putLoginInfo(JSON.stringify(clean));\n        \/\/ 校验只看 loginInfo 本身(不能用 uinfo(),它会被源变量兜底而掩盖失败)\n        var back = '';\n        try { back = _fkVal(_fkRawMap()[FKEY_NAME]); } catch (e3) {}\n        if (back.indexOf(fkeyItems(single)[0].name) < 0 && back.indexOf(single.split(';')[0]) < 0) {\n            try { src.putLoginInfo(raw0); } catch (e4) {}    \/\/ 回写失败则还原\n        }\n    } catch (e5) {}\n    return n;\n}\n\n\/* 诊断:把真实读到的一切弹出来,便于定位 *\/\nfunction diagFkey() {\n    var L = [];\n    var src = _fkSrc();\n    L.push('① source 对象:' + (src ? '可用' : '不可用'));\n    var rawInfo = '(读不到)';\n    try { rawInfo = src ? (src.getLoginInfo() + '') : '(无 source)'; } catch (e) { rawInfo = 'getLoginInfo() 异常: ' + e; }\n    L.push('② loginInfo 原始串(前400字):\\n' + String(rawInfo).substring(0, 400));\n    var keys = [];\n    try { var mm = uinfo(); for (var k in mm) if (Object.prototype.hasOwnProperty.call(mm, k)) keys.push(k); } catch (e2) {}\n    L.push('③ 解析到字段(' + keys.length + '):' + keys.join(' \/ '));\n    var v = fkeyRaw();\n    L.push('④ 自定义分类 原文(前300字):\\n' + (String(v).trim() ? String(v).substring(0, 300) : '(空)'));\n    var sv = '(空)';\n    try { sv = src ? _fkVal(src.get('fkey')) : '(无 source)'; } catch (e3) {}\n    L.push('⑤ 源变量 fkey(前300字):\\n' + (String(sv).trim() ? String(sv).substring(0, 300) : '(空)'));\n    var arr = [];\n    var err = '';\n    try { arr = fkey(); } catch (e4) { err = e4 + ''; }\n    if (err) L.push('⑥ 解析异常:' + err);\n    else if (!arr.length) L.push('⑥ 解析结果:0 个(没识别出有效条目)');\n    else {\n        var names = [];\n        for (var i = 0; i < arr.length; i++) names.push('  ' + (i + 1) + '. ' + arr[i].split('::')[0]);\n        L.push('⑥ 解析结果:' + arr.length + ' 个\\n' + names.join('\\n'));\n    }\n    var txt = '🔧 自定义分类诊断\\n\\n' + L.join('\\n\\n');\n    try { java.setClipboard(txt); } catch (e5) {}\n    try { java.longToast('\\n' + txt + '\\n\\n(已复制到剪贴板)'); } catch (e6) {}\n    return txt;\n}\n\n\/* 校验:告诉用户当前识别到什么 *\/\nfunction checkFkey() {\n    var raw = fkeyRaw();\n    var tip;\n    if (!String(raw).trim()) {\n        tip = '❎ 没读到分类内容。\\n\\n'\n            + '请按下面顺序操作:\\n'\n            + '1) 在上面的「自定义分类」框里填内容\\n'\n            + '2) 点右上角 √ 保存(很关键,不保存读不到)\\n'\n            + '3) 再回到本页点「🧪校验分类」\\n\\n'\n            + '【格式】每行一个:\\n分类名::网址\\n\\n'\n            + '多个分类用 换行 \/ 分号 \/ 逗号 隔开都行。\\n'\n            + '在视频详情页长按简介里的分类或演员名,会自动复制成「名称::网址」。\\n\\n'\n            + '还是不行就点右边的「🔧诊断」把结果发我。';\n    } else {\n        var arr = [];\n        var err = '';\n        try { arr = fkey(); } catch (e) { err = e + ''; }\n        if (err) tip = '❎ 解析出错:' + err;\n        else if (!arr.length) tip = '❎ 读到了内容,但没识别出有效条目:\\n' + String(raw).substring(0, 300)\n            + '\\n\\n每条要像这样:分类名::https:\/\/mjv006.com\/zh\/xxx\/';\n        else {\n            var names = [];\n            for (var i = 0; i < arr.length; i++) names.push('  ' + (i + 1) + '. ' + arr[i].split('::')[0]);\n            tip = '✅ 已识别 ' + arr.length + ' 个分类:\\n\\n' + names.join('\\n')\n                + '\\n\\n返回后发现页生效(需重新进发现页)。';\n        }\n    }\n    java.longToast('\\n' + tip);\n}\n\n\/* 备份:写入源变量,避免 loginInfo 读取异常时丢失 *\/\nfunction saveFkey() {\n    var n = 0;\n    try { n = normFkey(); } catch (e) {}\n    if (!n) { try { n = fkeyCount(fkeyRaw()); } catch (e0) {} }\n    var raw = fkeyRaw();\n    if (!String(raw).trim()) {\n        java.longToast('\\n❎ 读到的内容为空。\\n请先填写 → 点右上角 √ 保存 → 再进本页点备份。\\n\\n若已保存仍读不到,点「🔧诊断」看原因。');\n        return;\n    }\n    java.longToast('\\n✅ 已备份 ' + n + ' 条:\\n\\n' + String(raw).substring(0, 300)\n        + '\\n\\n备份内容存在源变量 fkey 里,即使登录信息丢失也能恢复。');\n}\n\n\/* 清空备份 *\/\nfunction clearFkey() {\n    var src = _fkSrc();\n    try { if (src) src.put('fkey', ''); } catch (e) {}\n    java.longToast('\\n✅ 已清空备份的自定义分类。\\n(发现页会只剩内置分类,登录框里的内容不受影响)');\n}\n\/* =============== [自定义分类 · 修复块 end] =============== *\/\n\ntry { normFkey(); } catch (e) {}\n",
    "preload": true,
    "preloadJs": "window.java = java;\nwindow.run = (typeof run !== 'undefined') ? run : function () { return ''; };\nwindow.source = source;\nwindow.importScriptAwait = importScriptAwait;\nwindow.playu = function(url) {\n    \/\/[修复] 1) cache 在 WebView 中可能未注入,直接解引用会 ReferenceError 导致取不到播放链接\n    \/\/       2) 实测该站从加载到 m3u8 出现约需 10~13 秒(含大量广告请求),9 秒超时偏紧\n    var h = '';\n    try { h = (typeof cache != 'undefined' && cache && cache.get) ? (cache.get(url) + '') : ''; } catch (e) { h = ''; }\n    return webViewGetSourceAwait(h, url, null, \".+cdn.+\\\\.m3u8\", true, 15000);\n}",
    "ruleArticles": "<js>\nlet url = java.hexDecodeToString(result) + '';\nlet sf = url.replace(\/^http.{4}[^\\\/]+\/, '');\nurl = surl() + sf;\nlet webrh = cache.get(url) + '';\nif (webrh.length < 6999) {\n    webrh = java.ajax(url);\n    webrh = rrcheck(url, webrh);\n    let webr = org.jsoup.Jsoup.parse(webrh);\n    webr = webr.select('.posts>.post');\n    if (webr == '') {\n        result = [];\n    } else {\n        let fmurl = webr.first().select(\"img\").attr(\"src\");\n        if (fmurl == '') {\n            result = [];\n        } else {\n            \/\/正确网络加载\n            result = webr;\n            let cfm = true;\n            if (\/animation_list\\\/all|dt_list\\\/all\/.test(url)) {\n                cache.put(url, webrh, 3600 * 24 * 3);\n            } else if (\/content_news\\\/all\/.test(url)) {\n                let _e1 = (result.size() > 1) ? result.get(1) : null;\n            let fmurlmr = _e1 ? _e1.select(\"img\").attr(\"src\") : '';\n                source.put('fmurlmr', fmurlmr);\n                cache.put(url, webrh, 3600 * 24 * 2);\n            } else if (\/fc_search\\\/all\/.test(url)) {\n                cache.put(url, webrh, 3600 * 24 * 2);\n            } else if (\/uncensored_list\\\/all|chinese_list\\\/all\/.test(url)) {\n                cache.put(url, webrh, 3600 * 24);\n            } else {\n                if (!url.includes(\"_random\")) {\n                    cfm = false;\n                    switch (String(Date.now()).substr(-1)) {\n                        case \"1\":\n                            source.put('fmsj1', fmurl);\n                            break;\n                        case \"2\":\n                            source.put('fmsj2', fmurl);\n                            break;\n                        case \"3\":\n                            source.put('fmsj3', fmurl);\n                            break;\n                    }\n                }\n                cache.put(url, webrh, 3600 * 4);\n                \/\/其他分类\n            }\n\n            if (cfm) source.put('fm' + sf, fmurl);\n            \/\/有封面\n        }\n        \/\/有dom\n    }\n    \/\/没缓存\n} else {\n    let mk = cache.getFromMemory(url + '2') || 0;\n    cache.putMemory(url + '2', mk + 1);\n    let tmh = new Date().getHours();\n    if (\/content_news\\\/all|animation_list\\\/all|fc_search\\\/all\/.test(url)) {\n        mk > 2 && cache.delete(url);\n    } else if (mk > 1 || tmh > 1 && tmh < 4) {\n        cache.deleteMemory(url + '2');\n        cache.delete(url);\n    }\n    webrh = org.jsoup.Jsoup.parse(webrh);\n    result = webrh.select('.posts>.post');\n}\nresult\n<\/js>",
    "ruleContent": "@js:\nlet uu = java.hexDecodeToString(result) + '';\nresult = uu.replace(\/^https|[\\\/\\.\\_\\-\\:\\s]|html$\/g, '');\nlet ssurl = surl();\nlet url = ssurl + uu;\nif (uu.startsWith(\"http\")) url = uu;\nlet webr = cache.get(url) + '';\nif (webr.length < 6999) {\n    webr = java.ajax(url);\n    webr = rrcheck(url, webr);\n    cache.put(url, webr, 3600 * 24 * 20);\n}\nlet title = gets('h1.0@text', webr);\nlet pimg = gets('#player-wrap img@src', webr);\nlet yimgs = gets('.ut1_img_content_smallcg .img_smallcg_hc@html||.ut1_img_content_smallcg div@html', webr).replaceAll('https:\/\/', 'https:\/\/cdn.cdnjson.com\/pic.html?url=');\nlet jianjie = gets('.posts-inner-details-text,.actor-right-details-images,.posts-inner-details-text@html', webr).replaceAll('https:\/\/pics.', 'https:\/\/cdn.cdnjson.com\/pic.html?url=pics.');\n\n\nlet posts = org.jsoup.Jsoup.parse(webr).select('.video .posts');\nposts.select('video').remove();\n\n\/\/获取配置\nvar info = uinfo();\nvar pc = info['播放器'] || '默认';\n\/\/[修复] 未打开配置页时 info 各项为 undefined,会导致下面生成 0.u \/ undefined 而整块脚本崩溃\nvar _lv = String(info['滑动等级']==undefined?'':info['滑动等级']).charAt(0);\nif(!\/^[0-9]$\/.test(_lv)) _lv='3';\nvar _ff = Number(info['长按⏩倍速']); if(!(_ff>0)) _ff=3;\nvar _tz = Number(info['双击⏭️时间']); if(!(_tz>0)) _tz=10;\nlet imgc='';\nif (info['预览截图']=='✅') {\n    imgc = `<div class=\"img_content\">${yimgs}<\/div>`;\n}\nlet sjzt='';\nif (info['随机主题']=='✅') {\n        sjzt = `<h2 onclick=\"sjzt()\" style=\"text-align: center;\">▼随机主题▼<\/h2>${posts}`;\n}\n\nresult = `\n  <!DOCTYPE html>\n  <html lang=\"zh-CN\">\n  \n  <head>\n    <meta charset=\"UTF-8\">\n    <title>${rssArticle.sort}<\/title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n  <style>.artplayer-app{position:relative;display:block;width:100%;height:0;padding-bottom:56.25%;min-height:200px;background:#000;overflow:hidden;box-sizing:border-box}.artplayer-app>img{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover}.play-indicator{position:absolute;top:0;left:0;width:100%;height:100%;display:-webkit-box;-webkit-box-align:center;-webkit-box-pack:center;display:-webkit-flex;-webkit-align-items:center;-webkit-justify-content:center;display:flex;align-items:center;justify-content:center;font-size:44px;line-height:1;color:#fff;text-shadow:0 0 10px rgba(0,0,0,0.9);z-index:9;transform:none;-webkit-transform:none;margin:0}.av18-diag{margin:10px 0;padding:10px;border:1px solid #ff6600;background:#fff6e5;color:#333;font-size:13px;line-height:1.7;word-break:break-all;white-space:pre-wrap}<\/style><script>window.__err=[];window.addEventListener('error',function(e){try{window.__err.push(String(e.message)+' @'+(e.lineno||0));}catch(x){}});window.addEventListener('unhandledrejection',function(e){try{window.__err.push('promise:'+String(e.reason));}catch(x){}});<\/script>\n  <\/head>\n  \n  <body>\n    <div class=\"artplayer-app\">\n${pc == '默认'?'':'<img src=\"'+pimg+'\" width=\"100%\">'}\n<\/div>\n    <div class=\"jianjie\">\n    <h3 id=\"title\">${title}<\/h3>\n    ${imgc}\n    ${jianjie}\n    <div id=\"pyurl\"><\/div>\n    <br>\n    <\/div>\n    ${sjzt}\n    <br>\n    <br>\n    <script>\n    window.local = true;\n\/\/    window.run(\"toastjs\").then(r=>eval(r));\n    <\/script>\n    <script>\nconst posts=document.querySelector('.posts');\nfunction sjzt() {\n\tposts.classList.toggle('active');\n\t}\nlet mrp=${pc == '默认'};\nfunction setting() {\n\tlet art = new Artplayer({\n        container: '.artplayer-app',\n        poster: '${pimg}',\n        id: '${result}',\n        theme: '#ffad00',\n        autoplay: ${info['自动播放']=='✅'},\n        muted: false,\n        fullscreen: true,\n        autoSize: true,\n        autoMini: false,\n        playbackRate: true,\n        setting: true,\n        lock: true,\n        gesture: true,\n        fastForward: true,\n        autoPlayback: ${info['继续播放']=='✅'},\n        autoOrientation: true,\n      });\n    Artplayer.RECONNECT_TIME_MAX = 3;\n    Artplayer.LOG_VERSION = false;\n    Artplayer.PLAYBACK_RATE = [0.75, 1, 2, 4, 6];\n    Artplayer.AUTO_PLAYBACK_MAX=50;\n    Artplayer.MOBILE_DBCLICK_PLAY = false;\n    Artplayer.TOUCH_MOVE_RATIO = 0.${_lv};\n    Artplayer.FAST_FORWARD_TIME = 500;\n    Artplayer.FAST_FORWARD_VALUE=${_ff};\n    \n art.on('dblclick', (event) => {\n\t const tmz = ${_tz};\n     const clix = event.clientX;\n     const rwid = art.rect.width;\n\t if (clix < rwid \/ 3) art.backward = tmz;\n\t else if (clix > rwid * 2 \/ 3) art.forward = tmz;\n\t else art.toggle();\n});\n\nart.once('ready', () => {\nlet lo=localStorage.getItem(\"artplayer_settings\")+'';\nif (lo.length<9)\nlocalStorage.setItem('artplayer_settings',source.get('localS'));\nelse\nsource.put('localS',lo); \n});\n\nart.on('error', (ee, tt) => {\n    if (tt>2) {\n        source.put(\"av18${result}\", '');\n    }\n   });\nreturn art;\n}\n\nasync function init () {\nvar art = null;\n\/*[修复] 实测两件事,因此不再使用 Artplayer,改由 hls.js + 原生 video 播放:\n   1) 该站 CDN 有 Referer 防盗链:不带 Referer 必然 404。Artplayer \/ 外部播放器 \/ 系统播放器\n      都是拿裸 URL 去请求,一定失败;只有页面内由 WebView 发起的请求才会自动带上 Referer。\n   2) Artplayer 在这套参数下会抛 \"Cannot read properties of undefined (reading 'enabled')\",\n      且它依赖 unpkg.com,国内经常加载不到。 *\/\nmrp = false;\nlet srcurl = source.get(\"av18${result}\");\n if (!srcurl) {\n    try {\n         srcurl = await playu(\"${url}\");\n    } catch(err) {\n        console.log(err);\n        srcurl = '';}\n    if (srcurl.length > 9) {\n        source.put(\"av18${result}\", srcurl);\n    } else {\n        java.longToast('💔未获取到播放链接');\n        cache.delete(\"${url}\");\n    }\n  }\nconst u = srcurl;\nconst uok = (typeof u === 'string' && u.length > 9 && (u.indexOf('http:') === 0 || u.indexOf('https:') === 0));\nconst _tip = function (m) { try { java.longToast(m); } catch (e) {} };\n\nfunction _ensureDiagBox() {\n    var box = document.getElementById('av18diag');\n    if (!box) {\n        box = document.createElement('div');\n        box.id = 'av18diag';\n        box.className = 'av18-diag';\n        box.style.display = 'none';\n        var py = document.querySelector('.artplayer-app');\n        if (py && py.parentNode) py.parentNode.insertBefore(box, py.nextSibling);\n        else document.body.appendChild(box);\n    }\n    return box;\n}\nfunction _diag(obj) {\n    window.__diag = obj;\n    try { obj['页面地址'] = location.href; } catch (e0) {}\n    try { obj['页面错误'] = window.__err || []; } catch (e) {}\n    try { console.log('AV18DIAG ' + JSON.stringify(obj)); } catch (e2) {}\n    try {\n        var box = _ensureDiagBox();\n        box.textContent = '诊断信息(可截图发给开发者)' + String.fromCharCode(10) + JSON.stringify(obj, null, 1);\n        box.style.display = 'block';\n    } catch (e3) {}\n    return obj;\n}\n\n\/* ================= 播放器核心:hls.js + 原生 video ================= *\/\nconst HLS_CDN = [\n    'https:\/\/cdn.jsdelivr.net\/npm\/hls.js@1.5.17\/dist\/hls.min.js',\n    'https:\/\/unpkg.com\/hls.js@1.5.17\/dist\/hls.min.js',\n    'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/hls.js\/1.5.17\/hls.min.js',\n    'https:\/\/cdn.bootcdn.net\/ajax\/libs\/hls.js\/1.5.17\/hls.min.js'\n];\nconst _NL = String.fromCharCode(10);\n\nfunction _abs(base, p) {\n    p = String(p == null ? '' : p);\n    if (!p) return p;\n    if (p.indexOf('http:') === 0 || p.indexOf('https:') === 0) return p;\n    try { return new URL(p, base).href; } catch (e) {}\n    while (p.charAt(0) === '\/') p = p.substring(1);\n    var i = base.lastIndexOf('\/');\n    var dir = i > 0 ? base.substring(0, i + 1) : base + '\/';\n    return dir + p;\n}\nfunction _loadJs(src, ms) {\n    return new Promise(function (res, rej) {\n        var sc = document.createElement('script');\n        var done = false;\n        var t = setTimeout(function () { if (!done) { done = true; rej(new Error('超时')); } }, ms || 15000);\n        sc.src = src;\n        sc.onload = function () { if (!done) { done = true; clearTimeout(t); res(); } };\n        sc.onerror = function () { if (!done) { done = true; clearTimeout(t); rej(new Error('加载失败')); } };\n        document.head.appendChild(sc);\n    });\n}\nasync function _loadHls() {\n    var errs = [];\n    for (var i = 0; i < HLS_CDN.length; i++) {\n        try {\n            await _loadJs(HLS_CDN[i]);\n            if (typeof Hls !== 'undefined') return { ok: HLS_CDN[i], errs: errs };\n            errs.push(HLS_CDN[i] + ':已加载但无 Hls');\n        } catch (e) { errs.push(HLS_CDN[i].replace('https:\/\/', '') + ':' + e.message); }\n    }\n    return { ok: null, errs: errs };\n}\n\/* 把清单里的相对地址(含 AES key 的 URI)全部改写成绝对地址。\n   实测 EXT-X-KEY 的 URI 是相对的 aavv.vv,不改的话喂 blob: 后 hls.js 解析不到,会 fragLoadError。 *\/\nasync function _absPlaylist(mu) {\n    var r = await fetch(mu);\n    if (!r.ok) throw new Error('清单 HTTP ' + r.status + '(无 Referer 时 CDN 返回 404)');\n    var txt = await r.text();\n    return txt.split(_NL).map(function (line) {\n        var t = line.trim();\n        if (!t) return line;\n        if (t.charAt(0) === '#') {\n            var k = t.indexOf('URI=');\n            if (k < 0) return line;\n            var q1 = t.indexOf(String.fromCharCode(34), k);\n            var q2 = q1 < 0 ? -1 : t.indexOf(String.fromCharCode(34), q1 + 1);\n            if (q1 < 0 || q2 <= q1) return line;\n            return t.substring(0, q1 + 1) + _abs(mu, t.substring(q1 + 1, q2)) + t.substring(q2);\n        }\n        return _abs(mu, t);\n    }).join(_NL);\n}\n\/* 手势:双击左右快进 \/ 中间暂停,长按右侧倍速,横向拖动 Seek(替代 Artplayer 的那套) *\/\nfunction _bindControls(v) {\n    var FFV = ${_ff}, TMZ = ${_tz}, RATIO = 0.${_lv};\n    if (!(FFV > 0)) FFV = 3;\n    if (!(TMZ > 0)) TMZ = 10;\n    if (!(RATIO > 0)) RATIO = 0.3;\n    var pt = null, sx = 0, stime = 0;\n    function rect() { return v.getBoundingClientRect(); }\n    v.addEventListener('dblclick', function (ev) {\n        var r = rect(), x = ev.clientX - r.left;\n        if (x < r.width \/ 3) v.currentTime = Math.max(0, v.currentTime - TMZ);\n        else if (x > r.width * 2 \/ 3) v.currentTime = v.currentTime + TMZ;\n        else { if (v.paused) v.play(); else v.pause(); }\n    });\n    v.addEventListener('touchstart', function (ev) {\n        if (!ev.touches || !ev.touches.length) return;\n        var r = rect(), x = ev.touches[0].clientX - r.left;\n        sx = x; stime = v.currentTime;\n        if (x > r.width * 0.72) pt = setTimeout(function () { v.playbackRate = FFV; _tip('⏩ ' + FFV + ' 倍速'); }, 500);\n    }, { passive: true });\n    v.addEventListener('touchmove', function (ev) {\n        if (!ev.touches || !ev.touches.length) return;\n        var r = rect(), x = ev.touches[0].clientX - r.left;\n        if (Math.abs(x - sx) > 12) {\n            if (pt) { clearTimeout(pt); pt = null; v.playbackRate = 1; }\n            v.currentTime = Math.max(0, Math.min(v.duration || 0, stime + (x - sx) * RATIO));\n        }\n    }, { passive: true });\n    function endTouch() { if (pt) { clearTimeout(pt); pt = null; } v.playbackRate = 1; }\n    v.addEventListener('touchend', endTouch);\n    v.addEventListener('touchcancel', endTouch);\n}\nasync function _startPlay(pyv, mu) {\n    var h = await _loadHls();\n    if (!h.ok) {\n        _diag({ '失败环节': '加载 hls.js', '已尝试': h.errs, '说明': '四个 CDN 都不通,请检查网络' });\n        return null;\n    }\n    var pl;\n    try { pl = await _absPlaylist(mu); }\n    catch (e2) {\n        _diag({ '失败环节': '取 m3u8 清单', '原因': e2.message,\n                '说明': '该站 CDN 有 Referer 防盗链。若页面地址是 data: 或 about:blank,请求不会带 Referer,会直接 404' });\n        return null;\n    }\n    var v = document.createElement('video');\n    v.controls = true; v.playsInline = true;\n    v.setAttribute('webkit-playsinline', 'true');\n    v.setAttribute('x5-playsinline', 'true');\n    v.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;background:#000';\n    pyv.appendChild(v);\n    var burl = URL.createObjectURL(new Blob([pl], { type: 'application\/vnd.apple.mpegurl' }));\n    var hl = new Hls({ enableWorker: true });\n    hl.on(Hls.Events.ERROR, function (e3, dd) {\n        if (dd && dd.fatal) _diag({ '失败环节': '播放', '错误': dd.type + '\/' + dd.details });\n    });\n    hl.loadSource(burl);\n    hl.attachMedia(v);\n    _bindControls(v);\n    return v;\n}\n\nlet pyv = document.querySelector('.artplayer-app');\nif (!pyv) { pyv = document.createElement('div'); pyv.className = 'artplayer-app'; document.body.appendChild(pyv); }\n\/*[修复] 高度兜底:直接算像素高度写回,不依赖 aspect-ratio \/ min-height 是否被注入 *\/\nvar _sz = function () {\n    var w = pyv.clientWidth || document.documentElement.clientWidth || window.innerWidth || 360;\n    if (!w) { setTimeout(_sz, 80); return; }\n    pyv.style.height = Math.round(w * 9 \/ 16) + 'px';\n    pyv.style.paddingBottom = '0';\n};\n_sz();\nwindow.addEventListener('resize', _sz);\n\nvar _started = false, _ov = null;\nfunction _setOv(t) { if (_ov) _ov.textContent = t; }\nasync function _go() {\n    if (_started) return;\n    _started = true;\n    if (!uok) {\n        _tip('💔未获取到播放链接,请返回重试');\n        _diag({ '失败环节': '抓取 m3u8', 'srcurl长度': (u || '').length,\n                'playu可用': (typeof playu === 'function'), 'java可用': (typeof java !== 'undefined') });\n        return;\n    }\n    _setOv('⏳正在加载播放器…');\n    var v = await _startPlay(pyv, u);\n    if (!v) { _setOv('⚠️播放失败,见下方诊断'); return; }\n    if (_ov && _ov.parentNode) { try { _ov.parentNode.removeChild(_ov); } catch (e) {} _ov = null; }\n    try { v.play(); } catch (e4) {}\n}\n\nif (${info['自动播放']=='✅'}) _go();\nelse {\n    _ov = document.createElement('div');\n    _ov.className = 'play-indicator';\n    _ov.textContent = '▶️';\n    pyv.appendChild(_ov);\n    pyv.addEventListener('click', function () { _go(); });\n}\nif (${info['显示链接']=='✅'})\ndocument.getElementById(\"pyurl\").innerHTML=\\`<p>播放链接:<span>\\${u}<\/span><button onclick=\"copyText(this,'before')\" style=\"margin-left: 2ex;\">⎘复制<\/button><\/p>\\`;\n\t}\nsetTimeout(init, 50);\n<\/script>\n  <\/body>\n  <\/html>\n  `;",
    "ruleImage": "img@src",
    "ruleLink": "a.0@href\n<js>\nlet url=java.base64Encode(result.replace(\/^http.{4}[^\\\/]+\/,''));\nresult+`@js:'data:;base64,${url},{\"type\":\"18av\"}'`;\n<\/js>",
    "ruleNextPage": "page",
    "rulePubDate": ".con .meta@text",
    "ruleTitle": ".con a@text",
    "searchUrl": "data:;base64,{{java.base64Encode(\"\/zh\/fc_search\/all\/\"+key+\"\/\"+page+\".html\")}},{\"type\":\"18av\"}",
    "shouldOverrideUrlLoading": "if (url.includes(\"\/chinese_category\/\")) {\n\tjava.open(\"sort\",`data:;base64,{{java.base64Encode(\"${url.replace(\/[^\\\\\/].html\/,'')}\"+page+\".html\")}},{\"type\":\"18av\"}`);\n\ttrue\n}\nelse false",
    "showWebLog": true,
    "singleUrl": false,
    "sortUrl": "@js:\nvar _fk = \"\";\ntry { _fk = fkey().join(\"\\n\"); } catch (e) { _fk = \"\"; }\n`中文字幕::data:;base64,{{java.base64Encode(\"\/zh\/chinese_list\/all\/\"+page+\".html\")}},{\"type\":\"18av\"}\n每日更新::data:;base64,{{java.base64Encode(\"\/zh\/content_news\/all\/\"+tkey()+\".html\")}},{\"type\":\"18av\"}\n随机近作::data:;base64,{{java.base64Encode(\"\/zh\/chinese_random\/all\/index.html?t=\"+page)}},{\"type\":\"18av\"}\n随机所有::data:;base64,{{java.base64Encode(\"\/zh\/chinese_randomall\/all\/index.html?t=\"+page)}},{\"type\":\"18av\"}${_fk ? \"\\n\" + _fk : \"\"}`",
    "sourceComment": "地址发佈页:mm18vd.com、mm18news.com\n邮件到 ebnrks87@gmail.com 或 ebnrks88@gmail.com 获取最新网站网址。",
    "sourceGroup": "🙈",
    "sourceIcon": "https:\/\/gitee.com\/lyc486\/yuedu\/raw\/master\/0GP0yD.gif",
    "sourceName": "18AV",
    "sourceUrl": "https:\/\/mjv006.com",
    "startHtml": "@js:\n(function() {\n\n    var info = uinfo();\n    if (info['启动页'] != '✅') {\n        return '';\n    }\n\n    let su = surl();\n    let zm = source.get('fm' + \"\/zh\/chinese_list\/all\/1.html\") + '';\n    let wm = source.get('fm' + \"\/zh\/uncensored_list\/all\/1.html\") + '';\n    let sjd = source.get('fm' + \"\/zh\/chinese_random\/all\/index.html?t=1\") + '';\n    let sja = source.get('fm' + \"\/zh\/chinese_randomall\/all\/index.html?t=1\") + '';\n    let sjm = source.get('fm' + \"\/zh\/animation_random\/all\/index.html?t=1\") + '';\n    let gc = source.get('fm' + \"\/zh\/dt_list\/all\/1.html\") + '';\n    let dm = source.get('fm' + \"\/zh\/animation_list\/all\/1.html\") + '';\n    let mr = source.get('fmurlmr') + '';\n    let fmsj1 = source.get('fmsj1') + '';\n    let fmsj2 = source.get('fmsj2') + '';\n\n    return `<html>\n<head>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n    <title>18AV<\/title>\n<\/head>\n<body>\n    <div class=\"container\">\n        <form id=\"ss\">\n            <input type=\"text\" name=\"key\" id=\"searchkey\" placeholder=\"输入关键词\">\n            <button type=\"submit\">搜 索<\/button>\n        <\/form>\n<div class=\"history-container\">\n<div class=\"history-header\">\n<div class=\"history-title\">搜索历史<\/div>\n<button id=\"clearHistory\">清除记录<\/button>\n<\/div>\n<div id=\"historyList\"><\/div>\n<\/div>\n        <div id=\"fl\">\n            <div onclick=\"ff('中文字幕')\">${zm?`<img src=\"${zm}\" alt=\"暂无图片\">`:''}<span>中文字幕<\/span><\/div>\n            <div onclick=\"ff('高清无码')\">${wm?`<img src=\"${wm}\" alt=\"暂无图片\">`:''}<span>高清无码<\/span><\/div>\n            <div onclick=\"ff('动画动漫')\">${dm?`<img src=\"${dm}\" alt=\"动画动漫\">`:''}<span>动画动漫<\/span><\/div>\n            <div onclick=\"ff('随机近作')\">${sjd?`<img src=\"${sjd}\" alt=\"暂无图片\">`:''}<span>随机近作<\/span><\/div>\n            <div onclick=\"ff('随机所有')\">${sja?`<img src=\"${sja}\" alt=\"暂无图片\">`:''}<span>随机所有<\/span><\/div>\n            <div onclick=\"ff('随机动漫')\">${sjm?`<img src=\"${sjm}\" alt=\"暂无图片\">`:''}<span>随机动漫<\/span><\/div>\n            <div onclick=\"ff('每日更新')\">${mr?`<img src=\"${mr}\" alt=\"暂无图片\">`:''}<span>每日更新<\/span><\/div>\n            <div onclick=\"ff('国产自拍')\">${gc?`<img src=\"${gc}\" alt=\"暂无图片\">`:''}<span>国产自拍<\/span><\/div>\n            <div onclick=\"ff('自选分类')\">${fmsj2?`<img src=\"${fmsj2}\" alt=\"暂无图片\">`:''}<span>自选分类<\/span><\/div>\n            <div onclick=\"window.location.href='${su}\/zh\/chinese_categorylist\/list\/index.html'\">${fmsj1?`<img src=\"${fmsj1}\" alt=\"暂无图片\">`:''}<span>分类清单<\/span><\/div>\n        <\/div>\n        <div class=\"bottom-line\"><\/div>\n    <\/div>\n<\/body>\n<\/html>`;\n\n})();",
    "startJs": "const HISTORY_KEY = 'searchHistory';\nconst MAX_HISTORY_ITEMS = 10;\n        const ss = document.getElementById('ss');\n        const historyList = document.getElementById('historyList');\n        const clearHistoryBtn = document.getElementById('clearHistory');\n        const searchInput = document.getElementById('searchkey');\n        function performSearch(keyword) {\n            if (!(keyword.length>1)) return;\n            addHistoryItem(keyword);\n            searchInput.value=\"\";\n            java.open(\"sort\", JSON.stringify({ [keyword]: `data:;base64,{{java.base64Encode(\"\/zh\/fc_search\/all\"+\"\/${keyword}\/\"+page+\".html\")}},{\"type\":\"18av\"}` }));\n        }\n        \r\n        ss.addEventListener('submit', function (event) {\r\n            event.preventDefault();\r\n            const formData = new FormData(ss);\r\n            const key = formData.get('key');\r\n            if (key) {\n            \tperformSearch(key);\n           } else {\n           \tsearchInput.placeholder = \"输入关键词,亲\";\n           searchInput.focus();}\r\n        });\n\/\/const tt = new Intl.DateTimeFormat('zh-CN', {year: 'numeric', month: '2-digit', day: '2-digit'}).format(new Date()).replace(\/\\\/\/g, '-');\nconst fl = {\n\t\"中文字幕\":`data:;base64,{{java.base64Encode(\"\/zh\/chinese_list\/all\/\"+page+\".html\")}},{\"type\":\"18av\"}`,\n\t\t\"高清无码\":`data:;base64,{{java.base64Encode(\"\/zh\/uncensored_list\/all\/\"+page+\".html\")}},{\"type\":\"18av\"}`,\n\t\t\t\"随机近作\":`data:;base64,{{java.base64Encode(\"\/zh\/chinese_random\/all\/index.html?t=\"+page)}},{\"type\":\"18av\"}`,\n\t\t\t\t\"随机所有\":`data:;base64,{{java.base64Encode(\"\/zh\/chinese_randomall\/all\/index.html?t=\"+page)}},{\"type\":\"18av\"}`,\n\t\t\t\t\t\"国产自拍\":`data:;base64,{{java.base64Encode(\"\/zh\/dt_list\/all\/\"+page+\".html\")}},{\"type\":\"18av\"}`,\n\t\t\t\t\t\"每日更新\":`data:;base64,{{java.base64Encode(\"\/zh\/content_news\/all\/\"+tkey()+\".html\")}},{\"type\":\"18av\"}`,\n\t\t\t\t\t\"动画动漫\":`data:;base64,{{java.base64Encode(\"\/zh\/animation_list\/all\/\"+page+\".html\")}},{\"type\":\"18av\"}`,\n\t\t\t\t\t\"随机动漫\":`data:;base64,{{java.base64Encode(\"\/zh\/animation_random\/all\/index.html?t=\"+page)}},{\"type\":\"18av\"}`\n\t}\n        function ff(n) {\n        \tif (n=='自选分类') {\n        \t\t(async () => {\n        \t\t\tconst fkey = await window.run(\"uinfo()['自定义分类']\");\n        \t\t\tlet obj = {};\n        \t\t\tif (fkey.length>9) {\n        \t\t\tfkey.trim().split(\/\\s+\/).forEach(x=> {\n        \t\t\tlet [y1,y2] = x.split('::');\n        \t\t\tobj[y1]=`data:;base64,{{java.base64Encode(\"${y2.replace(\/\\d+\\.html$\/,'\"+page+\".html\"')})}},{\"type\":\"18av\"}`});\n        \t\tjava.open(\"sort\", JSON.stringify(obj));\n        \t\t} else alert(\"请在登录界面填写自定义分类\")\n})();\n        \t\treturn\n        \t\t}\n        \tlet url = fl[n];\n        \tif (url) java.open(\"sort\", JSON.stringify({ [n]: url}));\n        \t}\r\n\r\n        ss.style.animation = `fadeIn 0.6s ease-out forwards`;\r\n        document.querySelectorAll('#fl > div').forEach((child, index) => {\r\n            child.style.animation = `fadeIn ${0.8 + index * 0.3}s ease-out forwards`;\r\n        });\n        \nfunction loadHistory() {\n return JSON.parse(localStorage.getItem(HISTORY_KEY)) || [];\n}\nfunction saveHistory(history) {\nlocalStorage.setItem(HISTORY_KEY, JSON.stringify(history));\n}\nfunction addHistoryItem(keyword) {\n            let history = loadHistory();\n            history = history.filter(item => item !== keyword);\n            history.unshift(keyword);\n            if (history.length > MAX_HISTORY_ITEMS) {\n                history = history.slice(0, MAX_HISTORY_ITEMS);\n            }\n            saveHistory(history);\n            renderHistory();\n        }\nfunction removeHistoryItem(keyword) {\n            let history = loadHistory();\n            history = history.filter(item => item !== keyword);\n            saveHistory(history);\n            renderHistory();\n        }\nfunction clearHistory() {\n            if (confirm('确定要清除所有搜索历史吗?')) {\n                localStorage.removeItem(HISTORY_KEY);\n                renderHistory();\n            }\n        }\n\/\/ 显示历史\n        function renderHistory() {\n            const history = loadHistory();\n            historyList.innerHTML = '';\n            if (history.length === 0) {\n                historyList.innerHTML = '<div class=\"no-history\">暂无搜索历史<\/div>';\n                return;\n            }\n            \n            history.forEach(keyword => {\n                const item = document.createElement('div');\n                item.className = 'history-item';\n                item.innerHTML = `${keyword}<span class=\"fa-times\" data-keyword=\"${keyword}\">🗑️<\/span>`;\n                historyList.appendChild(item);\n                \n                \/\/ 点击搜索\n                item.addEventListener('click', (e) => {\n                    if (!e.target.classList.contains('fa-times')) {\n                        searchInput.value = keyword;\n                        performSearch(keyword);\n                    }\n                });\n                \n                \/\/ 处理删除按钮\n                const deleteBtn = item.querySelector('.fa-times');\n                deleteBtn.addEventListener('click', (e) => {\n                    e.stopPropagation();\n                    removeHistoryItem(keyword);\n                });\n            });\n        }\n\nclearHistoryBtn.addEventListener('click',clearHistory);        \nrenderHistory();\n\n\/\/console.log(document.documentElement.outerHTML);",
    "startStyle": "        * {\r\n            margin: 0;\r\n            padding: 0;\r\n            box-sizing: border-box;\r\n            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;\n            user-select: none;\r\n        }\r\n        ::-webkit-scrollbar {\r\n            display: none;\r\n        }\r\n        body {\r\n            display: flex;\r\n            justify-content: center;\r\n            min-height: 100vh;\r\n            background: linear-gradient(135deg, #617696 0%, #e4edf5 100%);\r\n            padding: 10px 20px 20px 20px;\r\n            color: #333;\r\n        }\r\n        .container {\r\n            width: 100%;\r\n            text-align: center;\r\n            background: rgba(255, 255, 255, 0.86);\r\n            border-radius: 24px;\r\n            box-shadow: 0 15px 50px rgba(0, 0, 0, 0.08);\r\n            position: relative;\r\n            overflow-y: auto;\r\n        }\r\n        .container::before {\r\n            content: '';\r\n            position: absolute;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 28px;\r\n            background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);\r\n        }\r\n        .bottom-line {\r\n            width: 100%;\r\n            height: 28px;\r\n            background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);\r\n        }\r\n        #ss {\r\n            display: flex;\r\n            justify-content: center;\r\n            align-items: center;\r\n            margin: 30px auto;\r\n            width: 100%;\r\n            position: relative;\r\n        }\r\n        #ss input[type=\"text\"] {\r\n            width: 60%;\r\n            padding: 0px 20px;\r\n            margin-right: 10px;\r\n            height: 60px;\r\n            font-size: 1.15rem;\r\n            border: 2px solid #e3eef9;\r\n            border-radius: 16px;\r\n            outline: none;\r\n            background: #ffffff;\r\n            color: #2c3e50;\r\n            box-shadow:\r\n                0 5px 20px rgba(0, 0, 0, 0.03),\r\n                inset 0 1px 3px rgba(0, 0, 0, 0.05);\r\n            transition: all 0.3s ease;\r\n        }\r\n        #ss input[type=\"text\"]::placeholder {\r\n            color: #b0c1d3;\r\n            font-weight: 400;\r\n        }\r\n        #ss input[type=\"text\"]:focus {\r\n            border-color: #4facfe;\r\n            box-shadow:\r\n                0 8px 25px rgba(79, 172, 254, 0.15),\r\n                inset 0 1px 3px rgba(0, 0, 0, 0.03);\r\n        }\r\n        #ss button {\r\n            position: relative;\r\n            width: 30%;\r\n            height: 40px;\r\n            padding: 0px;\r\n            font-size: 1.1rem;\r\n            font-weight: 600;\r\n            border: none;\r\n            border-radius: 12px;\r\n            background: linear-gradient(90deg, #3f8abc 0%, #177eae 100%);\r\n            color: white;\r\n            transition: all 0.3s ease;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n        }\r\n        #ss button:hover {\r\n            background: linear-gradient(90deg, #4290d4 0%, #1c98d2 100%);\r\n            transform: translateY(-2px);\r\n        }\r\n        #ss button:active {\r\n            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.3);\r\n            transform: translateY(1px);\r\n        }\r\n        #ss button i {\r\n            margin-right: 10px;\r\n            font-size: 1rem;\r\n        }\r\n        #fl {\r\n            display: flex;\r\n            flex-direction: column;\r\n            justify-content: center;\r\n            align-items: center;\r\n        }\r\n        #fl>div {\r\n            width: 300px;\r\n            aspect-ratio: 16\/9;\n            height: 169px;\r\n            overflow: hidden;\r\n            \/* 约束图片高度 *\/\r\n            border: 2px dotted;\r\n            margin-bottom: 10px;\r\n            position: relative;\r\n        }\r\n        #fl>div>span {\r\n            display: block;\n            z-index: 2;\r\n            position: absolute;\r\n            top: 3%;\r\n            right: 3%;\r\n            font-weight: bold;\r\n                        font-family: 'Microsoft YaHei', 'PingFang SC', 'Noto Sans CJK SC', 'Source Han Sans SC', 'Heiti SC', 'WenQuanYi Micro Hei', sans-serif;\n                        font-size: 15px;\r\n            text-shadow: 2px 2px 6px #333, 0 0 20px #1c98d2;\r\n            color: #16263a;\n            background-color: rgba(191, 220, 245, 0.6);\r\n            border-radius: 20px;\r\n            padding: 5px 10px;\r\n        }\r\n        #fl>div>img {\r\n            width: 100%;\r\n            height: 100%;\r\n            display: block;\r\n            object-fit: cover;\r\n            object-position: center center;\r\n            filter: brightness(0.9);\r\n        }\r\n        @keyframes fadeIn {\r\n            from {\r\n                opacity: 0;\r\n                transform: translateY(20px);\r\n            }\r\n            to {\r\n                opacity: 1;\r\n                transform: translateY(0);\r\n            }\r\n        }\n\n.history-container {\n            width: 90%;\n            max-width: 700px;\n            margin: 0 auto 25px;\n            padding: 15px;\n            background: rgba(255, 255, 255, 0.95);\n            border-radius: 16px;\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);\n            text-align: left;\n            animation: fadeIn 0.5s ease-out forwards;\n        }\n        .history-header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            margin-bottom: 12px;\n            padding-bottom: 10px;\n            border-bottom: 1px solid #eaeaea;\n        }\n        .history-title {\n            font-size: 1.2rem;\n            font-weight: 600;\n            color: #2c3e50;\n            display: flex;\n            align-items: center;\n        }\n        #clearHistory {\n            background: none;\n            border: none;\n            color: #888;\n            font-size: 0.9rem;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n            transition: color 0.2s;\n        }\n        #clearHistory:hover {\n            color: #ff6b6b;\n        }\n        #historyList {\n            display: flex;\n            flex-wrap: wrap;\n            gap: 10px;\n        }\n        .history-item {\n            background: rgba(79, 172, 254, 0.1);\n            border: 1px solid rgba(79, 172, 254, 0.3);\n            border-radius: 50px;\n            padding: 8px 10px 8px 16px;\n            font-size: 0.95rem;\n            transition: all 0.2s;\n            color: #3f8abc;\n            display: flex;\n            align-items: center;\n        }\n        .history-item:hover {\n            background: rgba(79, 172, 254, 0.2);\n            transform: translateY(-2px);\n            box-shadow: 0 3px 8px rgba(79, 172, 254, 0.2);\n        }\n.fa-times {\nmargin-left: 10px;\nfont-size: 10px;\nwidth: 10px;\n\t}",
    "style": "* {\n        margin: 0;\n        padding: 0;\n        box-sizing: border-box;\n      }\n      html,\n      body {\n        width: 100%;\n        overflow-x: hidden;\n        overflow-wrap: break-word;\n        word-break: break-all;\n      }\n      .artplayer-app {\n      position: relative;\n      display: block;\n      width: 100%;\n      height: 0;\n      padding-bottom: 56.25%;\n      min-height: 200px;\n      background: #000;\n      overflow: hidden;\n      box-sizing: border-box;\n    }\n      .play-indicator {\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      margin: 0;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 44px;\n      line-height: 1;\n      color: #fff;\n      text-shadow: 0 0 10px rgba(0, 0, 0, 0.9);\n      z-index: 9;\n      transform: none;\n    }\n      .img_content {\n        display: flex;\n        flex-wrap: wrap;\n        line-height: 0;\n        justify-content: space-between;\n      }\n      .img_smallcg_hc {\n          width:100vw;\n          height: auto;\n      }\n      .img_smallcg img {\n        width: 50vw;\n        height: auto;\n      }\n      .posts-inner-details-text-top {\n        display: flex;\n        flex-wrap: wrap;\n      }\n      .posts-inner-details-text-left ul {\n        display: flex;\n        width: 50vw;\n        flex-wrap: wrap;\n      }\n      .posts-inner-details-text-left li {\n        width: 25vw;\n        list-style: none;\n        flex-wrap: wrap;\n      }\n      .posts-inner-details-text-under li span {\n        margin-right: 1ex;\n      }\n      h3 {\n        margin: 1ex;\n      }\n      .posts {\n      \tmax-height: 0;\n      \toverflow: hidden;\n      \t}\n      \t.posts.active {\n      \tmax-height: max-content;\n      \t}",
    "type": 0
}
广告