微博
https://m.weibo.cn#微博整合
分享者: guaner001125 (317)发布时间: 07/28 17:54
1、需要登录 2、需要用洛雅橙大佬改版阅读3.26.032122版本及以上 v2.2 显示备注名 修复部分评论多张图片无法显示的问题 查看大图还有查看无水印图片 查看图片显示旋转和翻转图片的按钮 v2.1 正文添加加入书架按钮【需配合微博书源】 用户等主页添加复制发现链接按钮【需配合微博书源】 v2.0 显示部分分类URL,可以方便添加首页 修复部分评论图片是网络链接造成的评论错误 超话搜索更改为实时搜索 v1.9 查看超话,话题有很多分类 v1.8 评论图片更改显示方式 v1.7 优化实时分析的微博智搜显示 每次启动源获取登录cookie 修复转发图片无法打开的问题 修复有些评论图片不显示的问题 修复用户的视频不显示在列表的问题 v1.6 跳转验证时,与登录统一网址,避免无法记录正确cookie,尝试解决登录cookie总是掉的问题 v1.5 1.尝试修复用户列表无法加载的问题。 2.用户列表能查看精选、视频、相册分类。 3.微博正文能显示所有视频,并能播放live图。 v1.4 修复了一些小问题 v1.3 修复点击跳转登录有时无法正确加载页面的问题 v1.2 同步洛雅橙大佬改版阅读重要功能函数挂到window上,需先更新阅读版本,再导入源 v1.1 登录按钮处添加【我的关注】列表,可从微博拉取关注列表
{
"articleStyle": 0,
"cacheFirst": false,
"customOrder": 3,
"enableJs": true,
"enabled": true,
"enabledCookieJar": true,
"header": "@js:\nJSON.stringify({\n \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/128.0.0.0 Safari\/537.36\",\n \"sec-ch-ua-platform\":\"\\\"Android\\\"\",\n \"x-requested-with\":\"XMLHttpRequest\",\n \"mweibo-pwa\":\"1\",\n \"Referer\":\"https:\/\/m.weibo.cn\"\n})",
"injectJs": "var wrapElements = document.querySelectorAll('div.wrap');\nvar adWrapElements = document.getElementsByClassName('ad-wrap');\n\nfor (var i = 0; i < wrapElements.length; i++) {\n var wrapElement = wrapElements[i]; wrapElement.parentNode.removeChild(wrapElement);\n}\n\nwhile (adWrapElements.length > 0) {\n var adWrapElement = adWrapElements[0];\n adWrapElement.parentNode.removeChild(adWrapElement);\n}\n\naaaa = window.location.href;\n\nif(\/\\\/a\\\/\\d+\/.test(aaaa) && aaaa.includes(\"weibo\")){\n\twindow.location.href = window.location.href.replace(\/a\/,'detail');\n\t}\n\nif(\/ttarticle\/.test(aaaa)){\n\nfunction styleExtractedContent() {\n \n const originalContent = document.querySelector(\".main_editor\").innerHTML.replace(\/style=\"opacity.*?\"| \/g,'').replace(\/<br>\/g,'<br>  ');\n document.body.innerHTML = '';\n \n const styledContainer = document.createElement('div');\n styledContainer.className = 'styled-article'; \n styledContainer.innerHTML = originalContent;\n document.body.appendChild(styledContainer);\n const style = document.createElement('style');\n style.textContent = `\n .styled-article {\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n font-family: \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif;\n line-height: 1.8;\n color: #333;\n background: #fff;\n }\n \n .styled-article .title {\n font-size: 24px;\n font-weight: bold;\n margin-bottom: 20px;\n color: #222;\n text-align: center;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n }\n \n .styled-article .authorinfo {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 15px;\n border-bottom: 1px solid #f5f5f5;\n }\n \n .styled-article .W_face_radius {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n margin-right: 10px;\n vertical-align: middle;\n }\n \n .styled-article .author1 a {\n font-size: 16px;\n color: #333;\n text-decoration: none;\n }\n \n .styled-article .time {\n color: #999;\n font-size: 14px;\n }\n \n .styled-article .preface_v2 {\n font-style: italic;\n color: #666;\n margin-bottom: 25px;\n padding: 15px;\n background: #f9f9f9;\n border-left: 3px solid #ddd;\n }\n \n .styled-article *[node-type=\"contentBody\"] p {\n margin-bottom: 25px;\n text-align: justify;\n font-size: 16px;\n color: #222; \n text-indent: 1.7em; \n }\n \n .styled-article .artical_add_box {\n margin-top: 40px;\n padding: 20px;\n background: #fafafa;\n border-radius: 8px;\n }\n \n .styled-article .btn_bed a {\n display: inline-block;\n padding: 8px 15px;\n background: #ff8200;\n color: white;\n border-radius: 4px;\n text-decoration: none;\n }\n \n \n @media (max-width: 600px) {\n .styled-article {\n padding: 15px;\n }\n \n .styled-article .title {\n font-size: 20px;\n }\n \n .styled-article .WB_editor_iframe_new p {\n font-size: 15px;\n }\n }\n `;\n \n document.head.appendChild(style);\n}\n\n\nstyleExtractedContent();\n\n\n\t\n\t\n\t}",
"jsLib": "function S(e){\n\treturn String(this.java.getString(e));\n}\n\nfunction getU2S(t,id){\n\t const {source,java} = this;\n\t let jsonData = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}');\n\t let u = jsonData[t].find(u => String(u.id) === String(id));\n return u\n}\n\n\nfunction aitoHtml(text) {\n text = text.replace(\/<think>[\\s\\S]+?<\\\/think>\/,''); \n if(!text)return \"正在分析中......\"; \n let lines = text.split(\/<br>|\\n\/).filter(line => line.trim() !== '');\n let html = '';\n let currentListType = null;\n let inTable = false;\n let tableContent = '';\n let inBlock = false;\n let blockType = '';\n let blockContent = '';\n for(let i=0;i<lines.length;i++){\n let line = lines[i];\n let content=\"\";\n if(!line)continue;\n if(line.startsWith('## ')){\n content = line.replace(\/^## \/g,'');\n content = `<h3 class=\"ai-h3\">${content}<\/h2>`;\n html += content\n }\n else if(line.startsWith('### ')){\n content = line.replace(\/^### \/g,'');\n content = `<h3 class=\"ai-h3\">${content}<\/h3>`;\n html += content\n }\n else if(line.startsWith('#### ')){\n content = line.replace(\/^#### \/g,'');\n content = `<h4 class=\"ai-h4\">${content}<\/h4>`;\n html += content\n }\n else if(\/^(?:\\s*- |● )\/.test(line)){\n \t content = line.replace(\/^\\s*- |^● \/g,''); \t \n \t content = `<li class=\"ai-list\">${content}<\/li>`; \n html += content\n }\n else if(\/^\\s*\\|.*\\|\\s*$\/.test(line) && !inTable){\n \t inTable = true;\n \t tableContent += line +\"\\n\";\n }\n else if(inTable){\n if (line.match(\/^\\s*\\|.*\\|\\s*$\/)) {\n tableContent += line + '\\n';\n } else {\n html += processTable(tableContent.trim());\n inTable = false;\n tableContent = '';\n i--;\n }\n continue;\n }\n \n else if(\/^\\d+\\.\/.test(line)){\n content = `<p class=\"ai-listp\">${line}<\/p>`;\n html += content\n }\n else{\n content = line.replace(\/^> \/g,'');\n \t content = `<p class=\"ai-content\">${content}<\/p>`;\n html += content\n \t}\n \n }\n \nhtml = `<div id=\"ai-body\">${inlineFormat(html)}<\/div>`\nreturn html\n}\n\n\nfunction processTable(content) {\n const rows = content.split('\\n').filter(row => row.trim());\n if (rows.length < 2) return `<pre>${content}<\/pre>`;\n \n let tableHTML = '<table class=\"data-table\">';\n \n rows.forEach((row, index) => {\n if (row.match(\/^\\s*\\|[-:\\|]+\\|\\s*$\/)) return; \n const cells = row.split('|').filter(cell => cell.trim() !== '');\n if (cells.length === 0) return; \n if (index === 0) { \n tableHTML += '<thead class=\"ai-thead\"><tr class=\"ai-tr\">';\n cells.forEach(cell => {\n tableHTML += `<th class=\"ai-th\">${inlineFormat(cell.trim())}<\/th>`;\n });\n tableHTML += '<\/tr><\/thead><tbody class=\"ai-tbody\">';\n } else {\n \/\/ 表体\n tableHTML += '<tr class=\"ai-tbody-tr\">';\n cells.forEach(cell => {\n tableHTML += `<td class=\"ai-tbody-td\">${inlineFormat(cell.trim())}<\/td>`;\n });\n tableHTML += '<\/tr>';\n }\n });\n \n tableHTML += '<\/tbody><\/table>';\n return tableHTML;\n}\n\nfunction inlineFormat(text) {\n \n let result = text.replace(\/\\*\\*(.*?)\\*\\*\/g, '<strong>$1<\/strong>');\n \n result = result.replace(\/```.*?```\/g,'')\n .replace(\/<media-block>\/g,'<div class=\"media-block\"><div class=\"media-c\">')\n .replace(\/<\\\/media-block>\/g,'<\/div><\/div>')\n .replace(\/data-scheme=\".*?mid=(\\d+)[^\"]+\"\/g,`onclick=\"openContent('$1')\"`)\n .replace(\/<span class=\"(?:vator|nick|arrow)\"[^>]*?>[^<]*?<\\\/span>\/g,'')\n .replace(\/data-width=\\d+ data-height=\\d+\/g,'')\n return result;\n}\n\nfunction formatTime(dateStr) {\n const date = new Date(dateStr);\n const year = date.getFullYear();\n const month = date.getMonth() + 1; \n const day = date.getDate();\n const hours = date.getHours().toString().padStart(2, '0');\n const minutes = date.getMinutes().toString().padStart(2, '0');\n \n return `${year}年${month}月${day}日 ${hours}:${minutes}`;\n}\n\nfunction formatCount(count) {\n if (count < 10000) return count.toString(); \n const inWan = (count \/ 10000).toFixed(2);\n return inWan.endsWith('.00') \n ? `${inWan.split('.')[0]}万` \n : `${inWan}万`;\n}\n\nfunction getContent($) {\n let galleryItems = \"\",\n videos = \"\";\n let long_imgs = $.pics!==undefined ? $.pics : [];\n let long_video = $.page_info?.type === \"video\" ? $.page_info : {};\n \tif(long_imgs.length!==undefined) {\n galleryItems = long_imgs.map((img, i) =>{\n let type = \"\";\n if(img.type==\"livephoto\")type=\"live图\";\n if(img.type==\"video\")type=\"视频\";\n if(img.url.match(\/gif$\/))type=\"动图\";\n let onclick = img.videoSrc ?`onclick=\"java.openVideoPlayer('${img.videoSrc}','视频',false)\"`:\"\";\n type = type?`<div class=\"zoom-icon\">${type}<\/div>`:\"\";\n \n let originalImg = img?.large?.url?img?.large?.url:\"\";\n originalImg = originalImg.replace(\/(http.*?.sinaimg.cn\\\/).*?\\\/\/,'$1oslarge\/');\n \n return `<div class=\"gallery-item\" ${onclick}>\n <img src=\"${img.url}\" data-original=\"${originalImg}\" loading=\"lazy\">\n ${type}\n <\/div>`\n }\n ).join('');\n galleryItems = `<div class=\"image-gallery\">${galleryItems}<\/div>`;\n }\n if (JSON.stringify(long_video) !== \"{}\") {\n if (long_video.urls) {\n long_video = long_video.urls;\n videos = long_video.hevc_mp4_hd || long_video.mp4_720p_mp4 || long_video.mp4_hd_mp4 || long_video.mp4_ld_mp4\n } else {\n long_video = long_video.media_info;\n videos = long_video.stream_url_hd || long_video.stream_url \n }\n videos = `<div class=\"media-container\"><video src=\"${videos}\" controls poster=\"${$.page_info.page_pic.url}\"><\/video><\/div>`\n }\n let remarkName = this.getU2S(\"users\",$?.user?.id)?this.getU2S(\"users\",$?.user?.id).remarkName:\"\";\n remarkName = remarkName || $?.user?.remark;\n return `\n<div class=\"comment-item\">\n<div class=\"comment-user\">\n<img class=\"user-avatar\" src=\"${$?.user?.avatar_hd}\" onclick=\"openUser('${$?.user?.id}')\">\n<div class=\"user-info\">\n<span class=\"user-name\" onclick=\"openUser('${$?.user?.id}')\">${remarkName ||$?.user?.screen_name}<span class=\"remark\">${remarkName?\" @\"+$?.user?.screen_name:\"\"}<\/span><\/span>\n<span class=\"comment-time\">${formatTime($.created_at)}<\/span><\/div>\n<div class=\"like_counts\"><span>♡${formatCount($.attitudes_count)}<\/span><\/div>\n<\/div>\n<div class=\"comment-text\">${$.text.replace(\/https?:\\\/\\\/m.weibo.cn\\\/\\d+\\\/(\\d+)\/g,'https:\/\/m.weibo.cn\/a\/$1').replace(\/'\\\/n\\\/\/g,\"'https:\/\/m.weibo.cn\/n\/\")}<\/div>\n${galleryItems}\n${videos}\n\n<\/div>`;\n\n}\n\nfunction liveUrl(href){\n\tconst {java} = this\r\n\t let res,id,url,body,stream_info,name;\r\n \tid = href.match(\/show\\\/(.*)\/)[1]; \r\n\t url = \"http:\/\/weibo.com\/l\/pc\/anchor\/live?live_id=\"+id;\r\n\t res = java.connect(url);\r\n\t body = JSON.parse(String(res.body()));\r\n\t if(body.error_code===27401)java.toast(\"直播不存在\");\r\n\t if(body.error_code===0){\r\n\t\t\tstream_info = body.data.item.stream_info;\n\t\t\tif(body.data.item.status === 5)java.toast(\"当前博主可能未开播\");\r\n\t\t\thref = stream_info.replay_url ? stream_info.replay_url.origin : stream_info.pull.live_origin_hls_url;\n\t\t\tname = body.data.item.desc\n }\r\n\nreturn {\n\t\"url\":href,\n\t\"name\":name\n\t}\n\n}\n\nfunction replaceLink(str){\n\tconst {java} = this;\n\tlet linkstyle = 'style=\"color:#1E88E5\"';\n\t return String(str)\n\/\/用户链接\n\n.replace(\/href=['\"][^\"]+?weibo.(?:com|cn)\\\/(u|profile)\\\/(\\d+)['\"]\/g,`onclick='openUser(\"$1\")' ${linkstyle}`)\n.replace(\/href=['\"]([^'\"]+?weibo.(?:com|cn)\\\/n\\\/[^\"']+)['\"]\/g,`onclick='openUser(\"$1\")' ${linkstyle}`)\n\n\/\/话题链接\n\n.replace(\/href=['\"][^\"']+?(?:containerid=(?:231522|100103)type%3D1|s.weibo.com\\\/weibo\\?q=)[^\"']+?%23(.*?)%23[^'\"]*?['\"]\/g, \n function(match, p1) {\n \n if(match.includes('ai.s.weibo.com\/api') || match.includes('m.s.weibo.com\/applink')) {\n return match;\n }\n \n \n let decoded = decodeURIComponent(p1); \n return `onclick='openUser(\"#${decoded}#\")' ${linkstyle}`;\n }\n)\n\n\/\/正文链接\n.replace(\/href=['\"][^'\"]*?(?:m\\.weibo\\.cn|weibo\\.com)*\\\/(?:\\d+\\\/\\d+|a|status|detail\\\/\\d+|(?:\\d+|status)\\\/[a-zA-Z\\d]{9,18})[^'\"]*?['\"]\/g,function(match, p1) {\n\t \n var match1 = match.match(\/\\\/(\\d+)\\??\"$\/);\r\n\t\tvar match2 = match.match(\/(?:\\d+|status)\\\/([a-zA-Z\\d]{9,13})\\??\/);\n var id = match1 ? match1[1] : (match2 ? match2[1] : \"\");\n if(id == \"\" || match.includes('ai.s.weibo.com\/api') || match.includes('m.s.weibo.com\/applink')){\n \t return match\n \t}\n return `onclick='openContent(\"${id}\")' ${linkstyle}`;\n })\n\n\/\/超话链接\n.replace(\/href=['\"][^'\"]+?(?:containerid=|\\\/p\\\/)([\\da-z]{30,60})[^'\"]*?['\"]\/g,`onclick='openUser(\"$1\")' ${linkstyle}`);\n\n}\n\n\nfunction getStarHtml(t,id,name,img,intro,desc,other,remarkName){\n\tconst {source,java} = this;\n\tlet url,openUrl;\n \n function getSuperUrl(name,url){\n let jsonAjax = java.ajax(url);\n let jsonData = JSON.parse(jsonAjax);\n let channel_list = jsonData.data.pageInfo?.cardlist_head_cards?.[0]?.channel_list;\n \n channel_list = channel_list ?? [{id:\"feed\",containerid:url.replace(\/.*?containerid=\/,'')}];\n let data = {};\n channel_list.forEach(tab=>{\n let u = `https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=`;\n if(tab.id == \"feed\"){\n data[name+\"的📝帖子\"] = u+tab.containerid+\"&since_id=\";\n data[\"📤帖子\"] = u+tab.containerid.replace(\/feed\/,'sort_time')+\"&since_id=\";\n data[\"🔥帖子\"] = u+tab.containerid.replace(\/feed\/,'recommend')+\"&since_id=\";\n data[\"💡帖子\"] = u+tab.containerid.replace(\/feed\/,'soul')+\"&since_id=\";\n }else if(\/\\d+\/.test(tab.id)){\n data[\"📝\"+tab.name] = u+tab.containerid+\"&since_id=\";\n data[\"📤\"+tab.name] = u+tab.containerid.replace(\/comment_sort\/,'status_sort')+\"&since_id=\";\n }else{\n data[tab.name] = u+tab.containerid+\"&since_id=\";\n }\n })\n \n return JSON.stringify(data)\n \n}\n \n function getHuatiUrl(id,name){\n return `https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=231522type%3D${id}%26t%3D10%26q%3D%23${name}%23&isnewpage=1&luicode=10000011&lfid=100103type%3D1%26q%3D${name}&page_type=searchall&page=1`;\n}\n let remark = this.getU2S(t,id)?this.getU2S(t,id).remarkName : \"\";\n remarkName = remark || remarkName;\n \n\tif(t === \"users\"){\n let m = \"https:\/\/m.weibo.cn\";\n \t\t let nname = \"👤\"+(remarkName || name);\n url = m+ \"\/api\/container\/getIndex?containerid=230413\"+id+\"_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&since_id=\";\n let userTopUrl = m+\"\/api\/container\/getIndex?type=uid&value=\"+ id;\n try{\n let userJsonData = java.ajax(userTopUrl);\n userJsonData = JSON.parse(userJsonData||\"{}\");\n if(userJsonData.ok===1){\n let tabsInfo = userJsonData.data.tabsInfo;\n let tabs = tabsInfo.tabs;\n let uu = {}\n let base = m+\"\/api\/container\/getIndex?type=uid&value=\";\n uu[nname+\"的微博\"] = url;\n tabs.forEach(x=>{\n switch(x.title){\n case \"精选\":\n url = base+id+\"&containerid=231002\"+id+\"_-_HOTMBLOG&page=1\"\n break;\n case \"视频\": \n case \"相册\":\n url = base+id+\"&containerid=\"+x.containerid+\"&since_id=\";\n break;\n }\n x.title!==\"微博\"? uu[x.title] = url:null\n });\n url = JSON.stringify(uu);\n }\n \n }catch(e){\n }\n openUrl = url;\n \n url = `https:\/\/m.weibo.cn\/u\/`+id;\n\t}else if(t === \"topics\"){\n\t\t\turl = `https:\/\/m.weibo.cn\/search?containerid=231522type%3D1%26t%3D10%26q%3D%23${id}%23`;\n\t\t\topenUrl = JSON.stringify({\n [\"💬\"+name+\"的综合\"]: getHuatiUrl(1,name),\n \"实时\": getHuatiUrl(61,name),\n \"图片\": getHuatiUrl(63,name),\n \"视频\": getHuatiUrl(64,name),\n \"关注\": getHuatiUrl(62,name),\n \"热门\": getHuatiUrl(60,name)\n });\n\t}else if(t === \"superTopics\"){\n\t\turl = `https:\/\/m.weibo.cn\/p\/index?containerid=${id}`;\n\t\topenUrl = `https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=${id}_-_feed`;\n openUrl = getSuperUrl(name,openUrl)\n }\n\t\n let desc1 = desc;\n if(desc.trim() != \"\"){\n desc =`<div class=\"star-url-section\">\n <div class=\"star-url-label\">简介:<\/div>\n <div class=\"star-url-content\" id=\"starContent\">${desc}<\/div>\n <div class=\"star-feedback\" id=\"starFeedback\"><\/div>\n <\/div>`\n }\n\t\n\treturn `<title>${name}<\/title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <div class=\"star-container\">\n <div class=\"star-header\">\n <div class=\"star-avatar-section\">\n <img src=\"${img}\" class=\"star-avatar\">\n <\/div>\n <div class=\"star-info\">\n <div class=\"starname\">${name}${remarkName?\"(\"+remarkName+\")\":\"\"}<\/div>\n <div class=\"star-count\">${intro}<\/div>\n <div class=\"star-tag\">${other}<\/div><br>\n <\/div>\n <\/div>\n \n <div class=\"star-action-buttons\">\n <button class=\"star-action-btn\" onclick=\"handleSubscribe()\">\n <span class=\"star-btn-icon\">👤<\/span>\n <span>${this.getU2S(t,id)?\"已订阅\":\"订阅\"}<\/span>\n <\/button>\n <button class=\"star-action-btn\" onclick=\"handleShare()\">\n <span class=\"star-btn-icon\">🔎<\/span>\n <span>查看<\/span>\n <\/button>\n <button class=\"star-action-btn\" onclick=\"handleJump()\">\n <span class=\"star-btn-icon\">🔗<\/span>\n <span>原链<\/span>\n <\/button>\n <button class=\"star-action-btn\" onclick=\"handleCopy()\">\n <span class=\"star-btn-icon\">✂️<\/span>\n <span>发现链接<\/span>\n <\/button>\n <\/div>\n ${desc}\n <\/div>\n \n <style>\n .star-container {\n max-width: 400px;\n margin: 0 auto;\n padding: 16px;\n background: #f8f9fa;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n min-height: 100vh;\n }\n \n .star-header {\n display: flex;\n align-items: flex-start;\n margin-bottom: 20px;\n padding: 16px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n }\n \n .star-avatar-section {\n margin-right: 12px;\n }\n \n .star-avatar {\n width: 60px;\n height: 60px;\n border-radius: 8px;\n object-fit: cover;\n border: 2px solid #e0e0e0;\n }\n \n .star-info {\n flex: 1;\n }\n \n .statname {\n font-size: 14px;\n font-weight: 600;\n color: #8b0000;\n margin-bottom: 4px;\n }\n \n .star-count {\n font-size: 12px;\n color: #666;\n margin-bottom: 6px;\n }\n \n .star-desc {\n font-size: 12px;\n color: #666;\n line-height: 1.4;\n margin-bottom: 4px;\n }\n \n .star-tag {\n font-size: 11px;\n color: #888;\n line-height: 1.3;\n }\n \n .star-action-buttons {\n display: flex;\n gap: 8px;\n margin-bottom: 20px;\n }\n \n .star-action-btn {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 12px 8px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n background: white;\n color: #666;\n font-size: 11px;\n cursor: pointer;\n transition: all 0.2s;\n }\n \n .star-action-btn:hover {\n background: #f5f5f5;\n transform: translateY(-1px);\n }\n \n .star-btn-icon {\n font-size: 16px;\n margin-bottom: 4px;\n }\n \n .star-url-section {\n padding: 16px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n }\n \n .star-url-label {\n font-size: 12px;\n color: #666;\n margin-bottom: 8px;\n font-weight: 500;\n }\n \n .star-url-content {\n padding: 12px;\n background: #f8f9fa;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 0.7em;\n line-height: 1.4;\n word-break: break-all;\n white-space: pre-wrap;\n margin-bottom: 12px;\n }\n \n .star-feedback {\n height: 18px;\n text-align: center;\n font-size: 10px;\n font-weight: 500;\n transition: all 0.3s;\n }\n \n @media (max-width: 480px) {\n .container {\n padding: 12px;\n }\n \n .star-header {\n padding: 12px;\n }\n \n .star-action-btn {\n padding: 10px 6px;\n font-size: 10px;\n }\n \n .star-btn-icon {\n font-size: 14px;\n }\n }\n <\/style>\n \n <script>\n function handleSubscribe() {\n const feedback = document.getElementById('starFeedback');\n try {\n let u = {\n \"id\":\"${id}\",\n \"name\":\"${name}\",\n \"desc\":(\\`${intro}${other?\"<br>\"+other:\"\"}${desc1?\"<br>\"+desc1:\"\"}\\`).replace(\/<br><br>\/g,'<br>'),\n \"avatar\":\"${img}\"\n };\n if(\"${remarkName}\")u.remarkName = \"${remarkName}\";\n let jsonData = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}');\n let existingUser = jsonData[\"${t}\"].find(user => String(user.id) === \"${id}\");\n if (!existingUser) {\n jsonData[\"${t}\"].push(u);\n source.putVariable(JSON.stringify(jsonData))\n }\n java.toast(\"订阅成功\");\n feedback.textContent = '订阅成功!';\n feedback.style.color = '#4CAF50';\n setTimeout(() => feedback.textContent = '', 2000);\n } catch(err) {\n feedback.textContent = '订阅失败';\n feedback.style.color = '#F44336';\n setTimeout(() => feedback.textContent = '', 2000);\n }\n }\n \n function handleJump() {\n window.open(\"${url}\");\n }\n \n function handleShare() { \n java.open(\"sort\",${\/^http\/.test(openUrl)?'\"'+openUrl+'\"':'JSON.stringify('+openUrl+')'},\"${name}\")\n }\n \n function handleCopy(){\n let url;\n switch(\"${t}\"){\n case \"users\":\n url = \"${name}::https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=107603${id}_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&page={\\\\{page}}\";\n break;\n case \"topics\":\n url = \"${name}::https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=231522type%3D1%26t%3D10%26q%3D${encodeURIComponent(\"#\"+id+\"#\")}&isnewpage=1&luicode=10000011&lfid=100103type%3D38%26q%3D${encodeURIComponent(id)}%26t%3D&page={\\{page}}\"\n break;\n case \"superTopics\":\n url = \"${name}::https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=${id}_-_feed&page={\\{page}}\"\n break;\n }\n copyText(url)\n }\n \n function copyText(text) {\n if (navigator.clipboard && navigator.clipboard.writeText) {\n navigator.clipboard.writeText(text).then(() => {\n java.toast(\"复制成功\\\\n\"+text)\n }).catch(err => {\n console.error('复制失败:', err);\n fallbackCopy(text);\n });\n } else {fallbackCopy(text);}\n }\n function fallbackCopy(text) {\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.style.position = 'fixed';\n textarea.style.opacity = '0';\n document.body.appendChild(textarea);\n textarea.select();\n try {\n const successful = document.execCommand('copy');\n if (successful) {console.log('复制成功(fallback):', text);\n } else {console.error('复制失败(fallback)');}\n } catch (err) {console.error('复制异常:', err);}\n document.body.removeChild(textarea);\n }\n \n \n <\/script>\n `;\n\t\n\t}",
"lastUpdateTime": 1785232415450,
"loadWithBaseUrl": true,
"loginUrl": "https:\/\/m.weibo.cn",
"preload": false,
"preloadJs": "window.java = java;\nwindow.run = run;\nwindow.source = source;\nwindow.webViewAwait = webViewAwait",
"ruleArticles": "<js>\nif(java.getString(\"$.errno||$.ok\")==\"-100\"){\n\t let url = String(java.getString(\"$.url\"));\t\n\t\tif(\/signin\/.test(url)){\n\t\t\tjava.longToast(\"请登录后刷新列表\")\n\t\t\tjava.startBrowser(url,\"验证\");\n \tjava.startBrowser(\"https:\/\/weibo.com\",\"验证\");\n\t\t}else{\n\t java.longToast(\"验证通过后请刷新列表\");\n java.startBrowser(url,\"验证\");\n }\n}\n\t\nif(result ==\"\"){\t\n\tjava.longToast(\"验证后请刷新列表\");\n\tjava.startBrowser(\"https:\/\/weibo.com\",\"登录\");\n\tjava.startBrowser(\"https:\/\/m.weibo.cn\",\"登录\");\n}\t\n\nif(!\/source.get\\(\"currentSearch\"\\)\/.test(baseUrl)){\n\tsource.put(\"currentSearch\",baseUrl);\n\t}\n\nresult\n<\/js>\n$.data.cards[*].card_group[*].users[*]&&data.cards[*].card_group[*]&&data.cards[*]&&$.data.statuses[*]&&data.cards[*].pics[*]&&$.data.cards[*].card_group[*].items[*]&&$.data.cards[*].card_group[*].pics[*]&&$.items[*]",
"ruleContent": "@js:\nlet jsLib = String(source.jsLib);\nif (\/huati\/.test(baseUrl)) {\n let huati = java.hexDecodeToString(src);\n result = `<title>刷新跳转【${huati}】<\/title><script>\n setTimeout(function() { \t \t \t\n java.open(\"sort\", \"${encodeURI(\"https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=231522type%3D1%26t%3D10%26q%3D%23\"+huati+\"%23&isnewpage=1&luicode=10000011&lfid=100103type%3D1%26q%3D\"+huati+\"&page_type=searchall&page=1\")}\",\"💬${huati}\");\n window.close()\n},8);\n<\/script>`;\n}else if (\/photo\/.test(baseUrl)) {\n let itemid = String(java.hexDecodeToString(src)).split(\"🖼🖼\");\n result = `<title>刷新跳转【${itemid[1]}】<\/title><script>\n setTimeout(function() {\n java.open(\"sort\", \"https:\/\/m.weibo.cn\/api\/container\/getSecond?containerid=${itemid[0]}&count=24&page=1\",\"🖼${itemid[1]!=\"\"?itemid[1]:\"全部图片\"}\");\n window.close()\n},8);\n<\/script>`;\n}else if(\/aisearch\/.test(baseUrl)){\n\tlet aiKey = String(java.hexDecodeToString(result)).split(\"❌\");\n\tlet q = aiKey[0];\n\tlet page_id = \"&page_id=\"+aiKey[1];\n\theader = {\n\t\t\"Referer\":\"https:\/\/m.s.weibo.com\/\"\n\t\t}\n \n if(\/^分析:htt\/.test(decodeURIComponent(q)))page_id=\"\";\n \n let body = \"query=\"+q+\"&content_type=loop&request_id=\"+Date.now()+\"&request_time=\"+Date.now()+\"&search_source=default_init&sid=h5_ai_share\"+page_id+\"&vstyle=1&cot=1&loop_num=1&query_id=\";\n \n\tlet aiUrl = `https:\/\/ai.s.weibo.com\/api\/wis\/show.json,{\"method\":\"POST\",\"body\":\"${body}\",\"headers\":${JSON.stringify(header)}}`;\n \n\tlet script = `\n let aiUrl = \\`${aiUrl}\\`;\n let aiAjax = java.ajax(aiUrl);\n \tlet aiData = JSON.parse(aiAjax).msg;\n let aiStatus = JSON.parse(aiAjax).status;\n document.body.innerHTML = aitoHtml(aiData);\n const interval = setInterval(() => {\n document.body.innerHTML = aitoHtml(aiData);\n if (aiStatus == 2) {\n clearInterval(interval); \n return;\n }\n aiAjax = java.ajax(aiUrl);\n aiData = JSON.parse(aiAjax).msg;\n aiStatus = JSON.parse(aiAjax).status;\n }, 1000); \n \n ${aitoHtml.toString()}\n ${processTable.toString()}\n ${inlineFormat.toString()}\n function openContent(id){\n java.open(\"rss\",\"https:\/\/weibo.com\/detail\/\"+id,\"微博内容\")\n }`;\n \n\tresult =\"<title>微博智搜<\/title><body><\/body><script>\"+script+\"<\/script>\"\n\t}else if(\/weibo.com\\\/detail\/.test(baseUrl)){\n\t java.toast(\"加载中\");\n let id = baseUrl.match(\/.*\\\/(.*)$\/)?.[1];\n let b = baseUrl.replace(\/weibo.com\/, 'm.weibo.cn');\n var html = java.ajax(b);\n\n try {\n var render_data = html.match(\/var \\$(render_data = \\[\\{[\\s\\S]+?\\|\\| \\{\\});\/)[1];\n eval(render_data);\n let $ = render_data.status;\n let longText = getContent($);\n let retweeted_status = $.retweeted_status ?? \"\";\n let retweeted_openurl = \"\";\n \n if (retweeted_status) {\n let id = retweeted_status.id;\n retweeted_openurl = `https:\/\/weibo.com\/detail\/${id}`;\n retweeted_status = getContent(retweeted_status)\n }\n retweeted_status = retweeted_status ? `<div class='retweeted_status' onclick=\"if(event.target === this)java.open('rss','${retweeted_openurl}')\">`+ retweeted_status + \"<\/div>\" : \"\";\n result = longText + retweeted_status;\n } catch (e) {\n java.log(e);\n result = JSON.parse(html).msg\n }\n \/\/链接匹配\n result = replaceLink(result)\n .replace(\/href=\"https?:\\\/\\\/weibo.cn\\\/sinaurl\\?u=([^'\"]+)\"\/g,function(x,n){\n let url = decodeURIComponent(n);\n \n if(\/(?:jpg|png|webp|jpeg|gif)$\/.test(url))\n return `onclick=\"java.showPhoto('${url}')\"`\n return x\n });\n \n result = `<div class=\"original-links\"><a href=\"${b.replace(\/detail\/,'a')}\" class=\"original-link\">🔗原文地址<\/a><a href=\"legado:\/\/import\/addToBookshelf?src=${b.replace(\/weibo.com\/,'m.weibo.cn')}\" class=\"original-link\">📚加入书架<\/a><\/div><div class=\"main-content\">${result}<\/div><div id=\"container\"><\/div>`;\n result = `<!DOCTYPE html>\n <html>\n <head><meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>微博详情<\/title>\n <link rel=\"stylesheet\" href=\"https:\/\/cdn.jsdelivr.net\/npm\/viewerjs@1.11.6\/dist\/viewer.min.css\">\n <script>\n \n${jsLib.match(\/(function formatTime[\\s\\S]+?)function get\/)[1]}\n \n${jsLib.match(\/(function replaceLink[\\s\\S]+?)function get\/)[1]}\n\n\nfunction getU2S(t,id){\n\t let jsonData = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}');\n\t let u = jsonData[t].find(u => String(u.id) === String(id));\n\t return u\n}\n\n function replaceurl(t){\n \n let text = String(t)\n .replace(\/href=(\\\\\/n\\\\\/[^\\\\s]+)\/g,'href=\\\"https:\/\/m.weibo.cn$1\\\"')\n .replace(\/\\\\\/\\\\\/s.weibo.com\\\\\/weibo\\\\?q=\/g,\"https:\/\/m.weibo.cn\/search?containerid=100103type%3D1%26q%3D\")\n .replace(\/https?:\\\\\/\\\\\/weibo.com\\\\\/\\\\d+\\\\\/(\\\\d+)\/g,'https:\/\/m.weibo.cn\/a\/$1').replace(\/https?:\\\\\/\\\\\/weibo.com\\\\\/p\\\\\/\/g,'https:\/\/m.weibo.cn\/p\/')\n .replace(\/href=\"https\\\\?:\\\\\/\\\\\/weibo.cn\\\\\/sinaurl\\\\?u=([^'\"]+)\"\/g,function(x,n){\n let url = decodeURIComponent(n);\n if(\/(?:jpg|png|webp|jpeg|gif)$\/.test(url))\n return \\`style=\"color:#1E88E5\" onclick=\"java.showPhoto('$\\{url}')\"\\`\n })\n .replace(\/href=\"([^\"]+?\\.(?:jpg|png|webp|jpeg|gif))\"\/g,\\`style=\"color:#1E88E5\" onclick=\"java.showPhoto('$1')\"\\`)\n \n \n return text\n }\n function getcomments(list, isReply = false) {\n return list.map(item => {\n let details = \"\";\n if (item.pic_num !== 0) {\n let url_structs = item.url_struct;\n var url_struct;\n for(let i in url_structs){\n url_struct = url_structs[i];\n if(url_struct.pic_ids && url_struct.pic_ids.length===item.pic_num) break;\n url_struct = {}; \n }\n let pic_ids = url_struct.pic_ids;\n pic_ids?pic_ids.forEach(x=>{\n let pic = url_struct.pic_infos[x]?.large?.url.replace(\/https?\/,'https');\n pic = pic.replace(\/(http.*?.sinaimg.cn\\\\\/).*?\\\\\/\/,'$1oslarge\/');\n let bmiddle = url_struct.pic_infos[x]?.bmiddle?.url.replace(\/https?\/,'https');\n details += \\`\n <div class=\"gallery-item\">\n <img src=\"$\\{bmiddle}\" data-original=\"$\\{pic}\" loading=\"lazy\">\n <\/div>\n \\`;\n }):null;\n details = \\`<div class=\"image-gallery\">$\\{details}<\/div>\\`;\n }\n \n let replies = \"\";\n if (item.comments && item.comments.length > 0) {\n replies = \\`<div class=\"comment-replies\">\n \\${getcomments(item.comments, true)}\n \\${item.total_number > 1 ? \\`\n <div class=\"morerep\" onclick=\"loadComments({id:'\\${item.id}',isReply:true})\">\n 共\\${item.total_number}条回复\n <\/div>\\` : ''}\n <\/div>\\`;\n }\n \n let remark = getU2S(\"users\",item?.user?.id)?getU2S(\"users\",item?.user?.id).remarkName:\"\";\n \n remark = remark || item.user.remark;\n return \\`\n <div class=\"comment-item\">\n <div class=\"comment-user\">\n <img class=\"user-avatar\" src=\"\\${item.user.avatar_hd}\" onclick=\"openUser('\\${item?.user?.id}')\">\n <div class=\"user-info\">\n <span class=\"user-name\" onclick=\"openUser('\\${item?.user?.id}')\">\\${remark||item.user.screen_name}<span class=\"remark\">\\${remark?\" @\"+item.user.screen_name:\"\"}<\/span><\/span>\n <span class=\"comment-time\">\\${formatTime(item.created_at)}<\/span>\n <\/div>\n <div class=\"like_counts\">\n <span>♡\\${formatCount(item.like_counts)}<\/span>\n <\/div>\n <\/div>\n <div class=\"comment-text\">\\${replaceLink(replaceurl(item.text).replace(\/(<img.*?>)\/g,'<span class=\"url-icon\">$1<\/span>'))}\\${details}<\/div>\n \n \\${replies}\n <\/div>\\`;\n }).join('');\n }\n <\/script>\n <\/head>\n<body>\n\n${result}\n\n<div class=\"float-buttons\">\n <button class=\"float-btn\" id=\"toTop\" title=\"回到顶部\">↑<\/button>\n <button class=\"float-btn\" id=\"toBottom\" title=\"回到底部\">↓<\/button>\n<\/div>\n<div id=\"starModal\" class=\"star-modal\">\n <div class=\"star-modal-content\">\n <span class=\"star-close-btn\" onclick=\"closestarModal()\">×<\/span>\n <div class=\"star-modal-body\" id=\"star-modalBody\"> <\/div>\n <\/div>\n<\/div>\n\n<\/body>\n\n\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/viewerjs@1.11.6\/dist\/viewer.min.js\"><\/script>\n<script>\n\n\/\/ 全局变量\nlet MaxId = []; \nlet repMaxId = []; \nlet currentMaxId = null;\nlet repCurrentMaxId = null;\nlet isLoading = false;\nlet repLoading = false;\nconst weiboId = \"${id}\";\nlet sortType = 0;\nlet repSortType = 0;\n\nfunction openUser(id){\n let remarkName,utype,thtml,name,img,intro,desc,other,url,jsonData;\n remarkName = \"\";\n if(\/^\\\\d+$|\\\\\/n\\\\\/\/.test(id)){\n if(\/\\\\\/n\\\\\/\/.test(id)){\n thtml = String(java.ajax(id));\n id = thtml.match(\/uid\",\"value\":\"(\\\\d+)\"\/)[1]\n }\n url = \"https:\/\/m.weibo.cn\/api\/container\/getIndex?type=uid&value=\"+id;\n jsonData = JSON.parse(String(java.ajax(url))).data.userInfo;\n utype = \"users\";\n name = jsonData.screen_name;\n remarkName = jsonData.remark || \"\";\n img = jsonData.avatar_hd;\n intro = \"粉丝:\"+jsonData.followers_count;\n other = jsonData.verified_reason;\n desc = jsonData.description;\n }else if(\/^#\/.test(id)){\n id = id.replace(\/^#|#$\/g,'');\n utype = \"topics\";\n url = \"https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=231522type%3D1%26t%3D10%26q%3D%23\"+id+\"%23&isnewpage=1&luicode=10000011&lfid=100103type%3D1%26q%3D\"+id+\"&page_type=searchall\";\n jsonData = JSON.parse(String(java.ajax(url))).data.cardlistInfo;\n name = id;\n img = jsonData.portrait;\n intro =(jsonData.cardlist_head_cards?.[0].head_data?.midtext??\"\").replace(\/详情>\/g,'');\n other = \"\";\n desc = jsonData.desc;\n }else{\n utype = \"superTopics\";\n url = \"https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=\"+id+\"_-_feed&page=1\";\n jsonData = JSON.parse(String(java.ajax(url))).data.pageInfo;\n name = jsonData.page_title;\n img = jsonData.portrait_hd\n intro = jsonData.desc_more[0];\n other = \"\";\n desc = jsonData.desc.replace(\/阅读.*?加关注签到发帖得经验值>>\/,'')+\"\\\\n\"+jsonData.desc_more[0];\n }\n run(\\`getStarHtml(\"\\${utype}\",\"\\${id}\",\"\\${name}\",\"\\${img}\",\"\\${intro}\",\\\\\\`\\${desc}\\\\\\`,\"\\${other}\",\"\\${remarkName}\");\\`)\n .then(r=>{\n let content = r.replace(\/<script>[\\\\s\\\\S]+<\\\\\/script>\/g,'');\n let scriptContent = r.match(\/<script>([\\\\s\\\\S]+)<\\\\\/script>\/)[1];\n \n const starmodal = document.getElementById('starModal');\n const starmodalBody = document.getElementById('star-modalBody');\n starmodalBody.innerHTML = content;\n starmodal.style.display = 'flex';\n \n if (document.getElementById('dynamicScript')) {\n script = document.getElementById('dynamicScript');\n script.parentNode.removeChild(script);\n }\n script = document.createElement('script');\n script.id = 'dynamicScript';\n script.textContent = scriptContent;\n document.body.appendChild(script);\n }).catch(e=>console.log(e))\n}\n\nfunction openContent(id){\n java.open(\"rss\",\"https:\/\/weibo.com\/detail\/\"+id,\"微博内容\")\n}\n\nfunction closestarModal() {\n const starmodal = document.getElementById('starModal');\n starmodal.style.display = 'none';\n const script = document.getElementById('dynamicScript');\n script.parentNode.removeChild(script);\n}\n\ndocument.getElementById('starModal').addEventListener('click', function(e) {\n if(e.target === document.getElementById('starModal')){\n document.getElementById('starModal').style.display = 'none';\n }\n})\n\n\n\/\/图片加载器\nfunction initImageViewer() {\n\tvar option = {\n\t\t url: 'data-original',\n\t \tmaxZoomRatio: 0.9,\n inline: false,\n movable: true,\n zoomable: true,\n toolbar: {\n zoomIn: 1,\n zoomOut: 1,\n oneToOne: 1,\n reset: 1,\n prev: 1,\n next: 1,\n rotateLeft: 1,\n rotateRight: 1,\n flipHorizontal: 1,\n flipVertical: 1\n } \n }; \n \n \n try { \n document.querySelectorAll('.image-gallery').forEach(x=>{new Viewer(x,option);});\n \n \n } catch (e) {\n \n \n }\n}\n\n\/\/ 获取评论函数\nasync function loadComments(options = {}) {\n const {\n id = weiboId,\n isReply = false,\n isLoadMore = false,\n targetElement = isReply ? '#reply-list' : '#container',\n tElement = isReply ? '#reply-list .comments-list' : '.comments-list',\n containerTemplate = null,\n sort = isReply ? repSortType : sortType\n } = options;\n const loadingFlag = isReply ? repLoading : isLoading;\n if (loadingFlag) return;\n isReply ? repLoading = true : isLoading = true;\n let url;\n if (isReply) {\n url = \\`https:\/\/weibo.com\/ajax\/statuses\/buildComments?flow=\\${sort}&is_reload=1&id=\\${id}&is_show_bulletin=2&is_mix=1&fetch_level=1&max_id=\\${isLoadMore ? repCurrentMaxId : 0}&count=20&locale=zh-CN\\`\n } else {\n url =\\`https:\/\/weibo.com\/ajax\/statuses\/buildComments?flow=\\${sort}&is_reload=1&id=\\${id}&is_show_bulletin=2&is_mix=0&count=20&fetch_level=0&locale=zh-CN\\`;\n if (isLoadMore && currentMaxId) {\n url += \\`&max_id=\\${currentMaxId}\\`;\n }\n }\n try {\n const response = await fetch(url, {\n headers: {\n 'Accept': 'application\/json',\n 'X-Requested-With': 'XMLHttpRequest'\n },\n credentials: 'include'\n });\n const data = await response.json();\n if (data.ok === -100) {\n if (\/error-message\/.test(document.querySelector(targetElement).innerHTML)) {\n throw new Error(\"需要登录\");\n }\n document.querySelector(targetElement).innerHTML += \\`<div class=\"error-message\">\n评论加载失败:请<a style=\"color:blue\" onclick=\"toLogin()\">访问首页或登录<\/a>后重试<\/div>\\`;\n throw new Error(\"需登录\");\n }\n const currentIdArray = isReply ? repMaxId : MaxId;\n const newMaxId = data.max_id;\n if (currentIdArray.includes(newMaxId)) {\n throw new Error(\"没有更多内容了\");\n }\n if (isReply) {\n repCurrentMaxId = newMaxId;\n repMaxId.push(newMaxId);\n } else {\n currentMaxId = newMaxId;\n MaxId.push(newMaxId);\n }\n \n const commentsData = data.data;\n if (isReply && !isLoadMore && !document.querySelector('.reply-modal')) {\n initReplyModal(id);\n }\n if (isLoadMore) {\n document.querySelector(tElement).innerHTML += getcomments(commentsData, isReply);\n \n \n initImageViewer();\n } else {\n if (data.ok === 0) throw new Error(\"没有内容\");\n let content = \\`<div class=\"comments-header\">\n <div class=\"comments-title\"><h3>评论(\\${formatCount(data.total_number)})<\/h3><\/div>\n <div class=\"sort-controls\">\n <button id=\"sortHot\" class=\"sort-btn \\${sortType===0?'active':''}\" onclick=\"loadComments({sort:0})\">热度<\/button>\n <button id=\"sortTime\" class=\"sort-btn \\${sortType===1?'active':''}\" onclick=\"loadComments({sort:1})\">时间<\/button><\/div>\n <\/div>\\`;\n const html = \\`<div class=\"comments-section\">\n \\${isReply?\"\":content} \n <div class=\"comments-list\">\\${getcomments(commentsData)}<\/div><\/div>\\`;\n \n document.querySelector(targetElement).innerHTML = html;\n \n initImageViewer();\n }\n} catch (error) {\n if (isLoadMore) {\n showToast(\/没有更多\/.test(error.message)?error.message:\"评论加载失败\")\n } else if (!\/没有内容|登录\/.test(error.message)) {document.querySelector(targetElement).innerHTML = \\`<div class=\"error-message\">评论加载失败: \\${error.message}<button onclick=\"loadComments(\\${JSON.stringify(options)})\">重试<\/button><\/div>\\`;\n }\n} finally {\n isReply ? repLoading = false : isLoading = false;\n}\n}\nfunction toLogin(){\n run('java.startBrowser(\"https:\/\/weibo.com\",\"登录\")');\n run('java.startBrowser(\"https:\/\/m.weibo.cn\",\"登录\")')\n}\nfunction initReplyModal(id) {\n const modal = document.createElement('div');\n modal.className = 'reply-modal';\n modal.dataset.commentId = id;\n modal.innerHTML = \\`\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h4>回复列表<\/h4>\n <div class=\"reply-sort\">\n <button class=\"sort-btn \\${repSortType===0?'active':''}\" onclick=\"loadComments({id:'\\${id}',isReply:true,sort:0});repSortType=0\" data-sort-type=0>热度<\/button>\n <button class=\"sort-btn \\${repSortType===1?'active':''}\" onclick=\"loadComments({id:'\\${id}',isReply:true,sort:1});repSortType=1\" data-sort-type=1>时间<\/button>\n <span class=\"close-btn\" onclick=\"this.closest('.reply-modal').remove();repMaxId=[];repSortType=0;repCurrentMaxId=null\">×<\/span>\n <\/div>\n<\/div>\n<div class=\"modal-body\" id=\"reply-list\"><\/div>\n<\/div>\\`;\n\ndocument.body.appendChild(modal);\nmodal.addEventListener('click', function(e) {\n if (e.target === modal) {\n modal.remove();\n repMaxId = [];\n repSortType = 0;\n repCurrentMaxId = null;\n }\n});\n\nconst replyList = document.querySelector(\"#reply-list\");\nif (replyList) {\n replyList.addEventListener('scroll', () => {\n if (replyList.scrollTop + replyList.clientHeight >= replyList.scrollHeight - 15) {\n loadComments({id:id,isLoadMore: true, isReply: true }); \n }\n});\n}\n}\n\nfunction showToast(message) {\n const toast = document.createElement('div');\n toast.textContent = message;\n toast.style.position = 'fixed';\n toast.style.bottom = '50px';\n toast.style.left = '50%';\n toast.style.transform = 'translateX(-50%)';\n toast.style.backgroundColor = 'rgba(0,0,0,0.7)';\n toast.style.color = 'white';\n toast.style.padding = '5px 5px';\n toast.style.borderRadius = '5px';\n toast.style.zIndex = '1000';\n document.body.appendChild(toast);\n setTimeout(() => {\n document.body.removeChild(toast);\n }, 1000);\n}\n\n\n\ndocument.getElementById('toTop').addEventListener('click', function() {\n if(document.querySelector(\"#reply-list\")){\n document.querySelector(\"#reply-list\").scrollTo({\n top: 0,\n behavior: 'smooth'\n });\n }else{\n window.scrollTo({\n top: 0,\n behavior: 'smooth'\n });\n }\n });\n \n\ndocument.getElementById('toBottom').addEventListener('click', function() {\n if(document.querySelector(\"#reply-list\")){\n document.querySelector(\"#reply-list\").scrollTo({\n top: document.querySelector(\"#reply-list\").scrollHeight,\n behavior: 'smooth'\n });\n }else{\n window.scrollTo({\n top: document.body.scrollHeight,\n behavior: 'smooth'\n });\n }\n});\n\nwindow.addEventListener('scroll', function() {\n const toTopBtn = document.getElementById('toTop');\n const toBottomBtn = document.getElementById('toBottom');\n const scrollPosition = window.scrollY;\n if (scrollPosition === 0) {\n toTopBtn.style.opacity = '0.5';\n toTopBtn.style.pointerEvents = 'none';\n } else {\n toTopBtn.style.opacity = '1';\n toTopBtn.style.pointerEvents = 'auto';\n }\n if (window.innerHeight + scrollPosition >= document.body.scrollHeight - 50) {\n toBottomBtn.style.opacity = '0.5';\n toBottomBtn.style.pointerEvents = 'none';\n } else {\n toBottomBtn.style.opacity = '1';\n toBottomBtn.style.pointerEvents = 'auto';\n }\n});\n\ndocument.addEventListener('DOMContentLoaded', () => {\n \n \n initImageViewer();\n \n document.addEventListener('click', (e) => {\n if (e.target.id === 'sortHot') {\n if (sortType !== 0) {\n sortType = 0;\n e.target.classList.add('active');\n document.getElementById('sortTime').classList.remove('active');\n currentMaxId = null;\n MaxId = [];\n loadComments({sort:0}); \n }\n }\n if (e.target.id === 'sortTime') {\n if (sortType !== 1) {\n sortType = 1;\n e.target.classList.add('active');\n document.getElementById('sortHot').classList.remove('active');\n currentMaxId = null;\n MaxId = [];\n loadComments({sort:1}); \n }\n }\n\nif (e.target.classList.contains('sort-btn')) {\n const modal = e.target.closest('.reply-modal');\n if (modal) {\n const id = modal.dataset.commentId;\n repSortType = parseInt(e.target.dataset.sortType);\n document.querySelectorAll('.reply-modal .sort-btn').forEach(btn => {\n btn.classList.toggle('active', parseInt(btn.dataset.sortType) === repSortType);\n });\n repCurrentMaxId = null;\n repMaxId = [];\n }\n}\n});\n\nloadComments();\n\nwindow.addEventListener('scroll', () => {\n if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 50) {\n loadComments({ isLoadMore: true });\n }\n});\n\nfunction findScrollingElement() {\n const elements = document.querySelectorAll('*');\n for (const el of elements) {\n if (el.scrollHeight > el.clientHeight && el.scrollTop > 0) {\n return el;\n }\n }\n return document.documentElement; \n}\n\n});\n\n<\/script>\n<\/html>`;\n}\n\n\n\n\nresult",
"ruleDescription": "<js>\nresult = \"\";\nfunction hasH(str) {\n if(str.startsWith('#') && str.endsWith('#')){\n return str\n }\n return \"\"\n}\n\nlet user = S(\"$.screen_name||$.user.screen_name\");\nlet visible = S(\"$.visible\");\nlet s = S(\"$.scheme\").match(\/containerid=([\\da-z]{20,45})\/)?.[1];\nlet ht = hasH(S(\"$.title_sub\"));\nlet id,name,img,intro,desc,other;\nif(user && !visible){\n\tid = S(\"$.user.id||$.id\");\n\tname = user;\n\timg = S(\"$..avatar_hd\");\n remarkName = S(\"$.user.remark\");\n fsnum = S(\"$..followers_count\");\n\tintro = \"粉丝:\"+(\/万|亿|千\/.test(fsnum)?fsnum:formatCount(Number(fsnum)));\n \n\tdesc = S(\"$..description\");\n\tother = S(\"$..verified_reason\");\n\tresult = getStarHtml(\"users\",id,name,img,intro,desc,other,remarkName); \n\t}else if(s || ht){\n\t\tid = s || ht;\n\t\tlet f = \/^#\/.test(id);\n\t\tid = id.replace(\/^#|#$\/g,'');\n img = S(\"$.pic||$.left_tag_img\");\n name = S(\"$.title_sub||$.title||$.desc\");\n \tname = f?name.replace(\/^#|#$\/g,''):name;\n let desc = S(\"$.desc1\");\n let intro = S(\"$.desc2||$.desc_extr||$.desc\");\n result = getStarHtml((f?\"topics\":\"superTopics\"),id,name,img,intro,desc,\"\"); \n}else if(S(\"$.pic_ori||$.pic_big\")){\n let originalImg = S(\"$.pic_ori||$.pic_big\");\n originalImg = originalImg.replace(\/(http.*?.sinaimg.cn\\\/).*?\\\/\/,'$1oslarge\/');\n\tresult = ` <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><img width=\"100%\" src=\"${originalImg}\">`;\n\t}\nresult\n<\/js>",
"ruleImage": "{{$.pic_middle||$..bmiddle_pic||$..bmiddle.url||$..page_pic.url||$.mblog.page_info.page_pic.url||$.mblog.user.avatar_hd||$.avatar_hd||$.user.avatar_hd||$..avatar_hd||$.left_tag_img||$.pic##.*\\n+}},{\"headers\":{\"referer\":\"https:\/\/m.weibo.cn\"}}\n<js>##thumbnail##bmiddle<\/js>\n<js>##https?##https<\/js>",
"ruleLink": "$.pic_big||$.id||$.mblog.id||$.idstr||$.user.id||$.scheme||$.itemid||$.pic_ori||$.data.id\n@js:\nif(\/title=微博热搜\/.test(baseUrl)){\n\t let huati = \"{{$.desc}}\"; \n\t result = `http:\/\/www.baidu.com@js:'data:huati;base64,${java.base64Encode(huati)},{\"type\":\"weibo\"}'`; \n\t}else if(\/_photo\/.test(String(java.getString(\"$.itemid\")))){\n\t\tlet scheme = String(java.getString(\"$.scheme\"));\n\t\t\n\t\tlet itemid = (scheme?scheme.match(\/containerid=(.*?)&\/)?.[1]:null)??\"\";\n\t\tlet name = java.getString(\"$.title_sub||$.title\")+\" \"+java.getString(\"$.desc\")\n\t\tresult = `http:\/\/www.weibo.com@js:'data:photo;base64,${java.base64Encode(itemid+\"🖼🖼\"+name)},{\"type\":\"weibo\"}'`; \n\t}else if(String(java.getString(\"$.pic_ori||$.pic_big\"))){\n\t\t result = `http:\/\/www.weibo.com@js:'data:img;base64,${java.base64Encode(String(java.getString(\"$.pic_ori||$.pic_big\")))},{\"type\":\"weibo\"}'`; \n\n}else{\t\t \t\n result = \"https:\/\/weibo.com\/detail\/\"+(result.match(\/(\\d{5,})$\/)?.[1]??result)\n}",
"ruleNextPage": "@js:\npage = \"{{$.data.cardlistInfo.since_id||$.data.pageInfo.since_id}}\" || \"{{$.data.page||$.data.cardlistInfo.page}}\" || (\/%26t%3D10|100103type%3D\\d+\/.test(baseUrl)?(Number(baseUrl.match(\/page=(\\d+)\/)?.[1])+1):\"\");\nresult = baseUrl.replace(\/(&?(since_id|page)=)\\d*(#[\\da-zA-Z]+)?\/g,`$1${page}`);",
"rulePubDate": "{{let i=String(java.getString(\"$..icon\"));let icon=\/4_0.png\/.test(i)?\"✴️\":\/1_0.png\/.test(i)?\"🆕\":\/2_0.png\/.test(i)?\"🔥\":\/3_0.png\/.test(i)?\"✅\":\/_ads_\/.test(i)?decodeURI(i.match(\/_ads_(.*?)\\.\/)[1]):\"\";icon}} {{$.created_at&&$.data.created_at&&$.mblog.created_at&&$.description&&$.desc_extr&&$.desc1&&$.desc2&&$.desc}}\n@js:\nif(\/\\+0800\/.test(result) && \"{{$.screen_name}}\"==\"\"){\ndate=new Date(result);\ntime=date.getTime();\nfunction formatDate2(inputTime) {\n var date = new Date(inputTime);\n var y = date.getFullYear();\n var m = date.getMonth() + 1;\n m = m < 10 ? ('0' + m) : m;\n var d = date.getDate();\n d = d < 10 ? ('0' + d) : d;\n return y +'-' + m + '-' + d;\n};\n\nfunction formatDate(now) {\n var time = formatDate2(now)\n var date1 = new Date(now)\n var date2 = new Date()\n var date3 = date2.getTime() - date1.getTime()\n var days = Math.floor(date3 \/ (24 * 3600 * 1000))\n var leave1 = date3 % (24 * 3600 * 1000) \n var hours = Math.floor(leave1 \/ (3600 * 1000))\n var leave2 = leave1 % (3600 * 1000)\n var minutes = Math.floor(leave2 \/ (60 * 1000))\n var leave3 = leave2 % (60 * 1000)\n if (days < 1 && hours < 1) { return minutes + \"分前\" } else if (days < 1) { return hours + \"小时 \" + minutes + \"分前\" } else {\n if (days < 7) {\n return days + \"天 \" + hours + \"小时前 \"\n } else { return time }\n }\n}\nfunction formatCount(count) {\n if (count < 10000) return count.toString();\n const inWan = (count \/ 10000).toFixed(2);\n return inWan.endsWith('.00') \n ? `${inWan.split('.')[0]}万` \n : `${inWan}万`;\n}\n\n\nlet remark = S(\"$.user.remark||$.data.remark||$.mblog.user.remark\");\nremark = remark?\"(\"+remark+\")\" : \"\";\n\nresult = '📅 '+formatDate(time)+\" 📝\"+formatCount(S(\"$.comments_count||$.mblog.comments_count||$.data.comments_count\"))+\" ❤️\"+formatCount(S(\"$.attitudes_count||$.mblog.attitudes_count||$.data.attitudes_count\"))+\" @\"+S(\"$.user.screen_name||$.data.user.name||$.mblog.user.screen_name\")+remark;\n}\nresult = result.replace(\/\\n\/g,' ').replace(\/.*?\\+0800.*\/,S(\"$.verified_reason\")+\" \"+\"粉丝:\"+S(\"$.followers_count_str\"));",
"ruleTitle": "@js:\nlet top = String(java.getString(\"$.mblog.isTop\"))==\"1\"?\"【🔝置顶】\":\"\";\nlet text = String(java.getString(\"$.mblog.text||$.text||$.title_sub||$.title||$.screen_name||$.user.screen_name||$.desc||$.pic_id||$.data.text\")).replace(\/<.*?>|^(?:筛选|更多热门.{2,4}|相册专辑\\(?\\d*\\)?|(?:搜|查看)?[他她]的((?:全部)?微博|热门内容)|超话社区|(?:热门|实时)视频|相关合集|相关用户((\\d+\\+?))*)|全部微博\\(\\d+\\)$|实时微博|查看更多.*|话题主持人|更多关注.*\/g,'');\nlet remark = S(\"$.remark||$.user.remark\");\nremark = remark?\"(\"+remark+\")\" : \"\";\ntop+text+remark",
"searchUrl": "@js:\nlet t = source.get(\"currentSearch\");\nif(\/PROFILE_WEIBO\/.test(t)){\n\tlet id = t.match(\/230413(\\d+)\/)?.[1]\n\tresult =\"https:\/\/m.weibo.cn\/api\/container\/getIndex?disable_sug=1&diabled_eject_animation=1&disable_hot=0&trans_bg=0&disable_history=1&container_ext=profile_uid:\"+id+\"%7Cnettype:%7Cgps_timestamp:\"+Math.ceil(Date.now()\/1000)+\"&containerid=100103type%3D401%26t%3D10%26q%3D\"+key+\"&page_type=searchall&page=1\";\n\t}else if(\/containerid=[^_]+_-_\/.test(t)){\n\t\tid = t.match(\/containerid=([^_]+)\/)[1];\t\t\n\t\t\n\t\t\/*\n\t\t\t\/\/综合\n\t\tresult = `https:\/\/m.weibo.cn\/api\/container\/getIndex?extparam=%7B%22topicid%22%3A%221022%3A${id}%22%2C%22pagetype%22%3A%22index%22%7D&container_ext=type%3A563%7Cdisable_history%3A1%7Ccache_need%3A0%7Cforce_ejecttype%3Apresent&containerid=100303type%3D563%26q%3D${key}%26t%3D62&page=1&count=10&new_topic_header_recommend=1&new_topic_header=1&page_type=searchall`;\n\t\t*\/\n\t\t\t\n\t\t\t\n\t\t\t\/\/实时\n\t\t\tresult = `https:\/\/weibo.com\/ajax_proxy\/chaohua\/search_feeds?containerid=100103type%3D566%26q%3D${encodeURIComponent(key)}%26t%3D1%26sort%3Dtime&fid=100103type%3D566%26q%3D${encodeURIComponent(key)}%26t%3D1%26sort%3Dtime&flowId=100103type%3D566%26q%3D${encodeURIComponent(key)}%26t%3D1%26sort%3Dtime&count=15&discover_flow_enable=1&featurecode=10000085&image_type=heif&is_container=1&extparam=%7B%22topicid%22%3A%221022%3A${id}%22%2C%22pagetype%22%3A%22index%22%2C%22dfp%22%3A564%7D&page=1&max_id=0&search_vsid=,{\"headers\":{\"Referer\":\"https:\/\/weibo.com\/page\/${id}\/search?keyword=${encodeURIComponent(key)}\"}}`\n\t\t\n\t\t}else{\n\t\t\tjava.toast(\"此项无法搜索\")\n}\nresult",
"shouldOverrideUrlLoading": "if(url == \"https:\/\/m.weibo.cn\/\"){\n java.startBrowser(\"https:\/\/m.weibo.cn\/\",\"登录\")\n\ttrue\n}else if(\/l\\\/wblive\/.test(url)){\n\ttry{\n let liveu = liveUrl(url);\n java.openVideoPlayer(liveu.url,liveu.name,true);\n true\n }catch(e){\n java.log(e)\n\t}\n\t}else if(\/jjwxc.*?(?:novelid=\\d+|book2(?:\\\/|%2F)\\d+)|(?:gongzicp\\.com.*?(?:novel-|novelId=|\\?id=)\\d+)\/.test(decodeURIComponent(url))){\n url = decodeURIComponent(url);\n\tid = url.match(\/.*?(?:novel[iI]d=|novel-|book2\\\/|\\?id=)(\\d+)\/)?.[1];\n\tif(\/jjwxc\/.test(url)){\n addurl = \"https:\/\/app-cdn.jjwxc.net\/androidapi\/novelbasicinfo?novelId=\"+id;\n }else{\n\t\taddurl = \"https:\/\/webapi.gongzicp.com\/webapi\/novel\/novelInfo?id=\"+id\n }\n\tjava.addBook(addurl);\n true\n}else if(\/ai\\.s\\.weibo|s\\.weibo\\..*?q=(?:回答:|分析:)|s\\.weibo\\..*?share_page_id|m.s.weibo.com\\\/applink\/.test(decodeURIComponent(decodeURIComponent(url)))){\n\turl = decodeURIComponent(decodeURIComponent(url));\n\tq = url.match(\/q=(.*?)&t\/)?.[1]??url.match(\/\"mid\": \"(\\d+)\"\/)?.[1]??\"\";\n if(\/^\\d+$\/.test(q)){ \t\n uid = url.match(\/\"mid_uid\":\\s*(\\d+)\/)?.[1]??\"\";\n q = \"分析:https:\/\/weibo.com\/\"+uid+\"\/\"+q;\n }\n \n q = encodeURIComponent(q);\n \n\tpage_id = url.match(\/share_page_id=(.*?)&\/)?.[1]??url.match(\/page_id\": \"([^\"]+)\",\/)?.[1]??\"\";\n\taiurl = `http:\/\/www.baidu.com@js:'data:aisearch;base64,${java.base64Encode(q+\"❌\"+page_id)},{\"type\":\"weibo\"}'`;\n\tjava.open(\"rss\",aiurl,\"微博智搜\");\n\ttrue\n}else if(\/weibo.cn\\\/sinaurl\\?u=\/.test(url)){\t \n\t url = decodeURIComponent(decodeURIComponent(url)).match(\/\\?u=(.*)\/)[1];\n\t java.toast(\"正在跳转其他网页...\");\n java.startBrowser(url,\"其他网页\")\n true\n}\n",
"showWebLog": true,
"singleUrl": false,
"sortUrl": "@js:\nlet r = \"\";\nlet s = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}');\n\nfunction getSuperUrl(name,id){\n let r = \"\";\n name = \"💎\"+name;\n let u = `https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=${id}_-_feed&since_id=\\n`;\n r += name+\"📝最新评论帖子::\" + u\n r += name+\"📤最新发布帖子::\" + u.replace(\/feed\/,'sort_time');\n r += name+\"🔥推荐帖子::\"+ u.replace(\/feed\/,'recommend');\n r += name+\"💡精华帖子::\"+u.replace(\/feed\/,'soul');\n return r\n}\n\n\nfunction getHuatiUrl(id,name){\n return `https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=231522type%3D${id}%26t%3D10%26q%3D%23${name}%23&isnewpage=1&luicode=10000011&lfid=100103type%3D1%26q%3D${name}&page_type=searchall&page=1\\n`;\n\n}\n\n\nfunction getUserUrl(id,name){\n let r = \"\";\n let m = \"https:\/\/m.weibo.cn\";\n name = \"👤\"+name;\n let url = m+ \"\/api\/container\/getIndex?containerid=230413\"+id+\"_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&since_id=\";\n let base = m+\"\/api\/container\/getIndex?type=uid&value=\";\n r += name+\"::\"+url+\"\\n\"\n return r\n}\n\nlet users = s.users;\nusers.forEach(x=>{\n r += getUserUrl(x.id,x.name)\n})\n\n\nlet superTopics = s.superTopics;\nsuperTopics.forEach(x=>{\n r += getSuperUrl(x.name,x.id);\n})\n\nlet topics = s.topics;\ntopics.forEach(x=>{\n let n = x.name;\n let name = \"💬\"+ x.name;\n r += name+\"综合::\"+getHuatiUrl(1,n)\n r += name+\"实时::\"+getHuatiUrl(61,n);\n r += name+\"图片::\"+getHuatiUrl(63,n);\n r += name+\"视频::\"+getHuatiUrl(64,n);\n r += name+\"关注::\"+getHuatiUrl(62,n);\n r += name+\"热门::\"+getHuatiUrl(60,n);\n})\n\n\nr",
"sourceComment": "1、需要登录\n2、需要用洛雅橙大佬改版阅读3.26.032122版本及以上\n\n\nv2.2\n显示备注名\n修复部分评论多张图片无法显示的问题\n查看大图还有查看无水印图片\n查看图片显示旋转和翻转图片的按钮\n\nv2.1\n正文添加加入书架按钮【需配合微博书源】\n用户等主页添加复制发现链接按钮【需配合微博书源】\n\nv2.0\n显示部分分类URL,可以方便添加首页\n修复部分评论图片是网络链接造成的评论错误\n超话搜索更改为实时搜索\n\nv1.9\n查看超话,话题有很多分类\n\nv1.8\n评论图片更改显示方式\n\nv1.7\n优化实时分析的微博智搜显示\n每次启动源获取登录cookie\n修复转发图片无法打开的问题\n修复有些评论图片不显示的问题\n修复用户的视频不显示在列表的问题\n\nv1.6\n跳转验证时,与登录统一网址,避免无法记录正确cookie,尝试解决登录cookie总是掉的问题\n\nv1.5\n1.尝试修复用户列表无法加载的问题。\n2.用户列表能查看精选、视频、相册分类。\n3.微博正文能显示所有视频,并能播放live图。\n\nv1.4\n修复了一些小问题\nv1.3\n修复点击跳转登录有时无法正确加载页面的问题\nv1.2\n同步洛雅橙大佬改版阅读重要功能函数挂到window上,需先更新阅读版本,再导入源\nv1.1\n登录按钮处添加【我的关注】列表,可从微博拉取关注列表",
"sourceGroup": "阅读",
"sourceIcon": "https:\/\/is1-ssl.mzstatic.com\/image\/thumb\/Purple221\/v4\/52\/6a\/04\/526a04f7-ccfd-612e-64cb-ece08b01b4e6\/WeiboAppIcon-0-0-1x_U007epad-0-1-0-0-85-220.png\/492x0w.webp",
"sourceName": "微博",
"sourceUrl": "https:\/\/m.weibo.cn#微博整合",
"startHtml": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>微博订阅<\/title>\n<\/head>\n<body>\n <div class=\"container\">\n <div class=\"sub-options\">\n <div class=\"category-tabs\">\n <button class=\"category-tab active\" data-category=\"user\">博主<\/button>\n <button class=\"category-tab\" data-category=\"super\">超话<\/button>\n <button class=\"category-tab\" data-category=\"topic\">话题<\/button>\n <\/div>\n <div class=\"search-box\">\n <input type=\"text\" placeholder=\"搜索当前列表(搜索空内容显示全部)\">\n <button class=\"search-btn\">搜索<\/button>\n <\/div>\n <\/div>\n\n \n <div class=\"content-area\">\n <div class=\"subscribe-list\" id=\"subscribe-list\">\n <!-- 订阅列表-->\n <\/div>\n <\/div>\n <\/div>\n\n <!-- 底部按钮区域 -->\n <div class=\"bottom-buttons\">\n <button class=\"bottom-button\" data-type=\"search\">\n <span class=\"bottom-button-icon\">🔍<\/span>\n <span class=\"bottom-button-text\">搜索<\/span>\n <\/button>\n <button class=\"bottom-button\" data-type=\"hot\">\n <span class=\"bottom-button-icon\">🔥<\/span>\n <span class=\"bottom-button-text\">热搜<\/span>\n <\/button>\n <button class=\"bottom-button\" data-type=\"hotlist\">\n <span class=\"bottom-button-icon\">❤️<\/span>\n <span class=\"bottom-button-text\">热门<\/span>\n <\/button>\n <button class=\"bottom-button\" data-type=\"login\">\n <span class=\"bottom-button-icon\">👤<\/span>\n <span class=\"bottom-button-text\">登录<\/span>\n <\/button>\n <\/div>\n\n <!-- 搜索弹窗 -->\n <div class=\"search-modal\" id=\"search-modal\">\n <div class=\"search-modal-content\">\n <div class=\"search-modal-header\">\n <h3 class=\"search-modal-title\">搜索<\/h3>\n <button class=\"search-modal-close\" id=\"search-modal-close\">×<\/button>\n <\/div>\n <input type=\"text\" class=\"search-modal-input\" id=\"search-modal-input\" placeholder=\"输入搜索关键词\">\n <div class=\"search-history\">\n <div class=\"search-history-title\"><a>历史搜索<\/a> <span id=\"search-clear\" class=\"search-clear\">×清空历史<\/span><\/div>\n \n <div class=\"search-history-list\" id=\"search-history-list\">\n <!-- 历史搜索记录会通过JS动态生成 -->\n <\/div>\n <\/div>\n <div class=\"search-modal-actions\">\n <button class=\"search-modal-cancel\" id=\"search-modal-cancel\">取消<\/button>\n <button class=\"search-modal-confirm\" id=\"search-modal-confirm\">确认<\/button>\n <\/div>\n <\/div>\n <\/div>\n \n <!-- 登录弹窗 -->\n <div class=\"login-modal\" id=\"login-modal\">\n <div class=\"login-modal-content\">\n <div class=\"login-modal-header\">\n <h3 class=\"login-modal-title\">登录<\/h3>\n <button class=\"login-modal-close\" id=\"login-modal-close\">×<\/button>\n <\/div>\n \n <div class=\"login-modal-actions\">\n <button class=\"login-modal-my\" id=\"login-modal-my\">我的关注<\/button>\n <button class=\"login-modal-cancel\" id=\"login-modal-cancel\">跳转登录<\/button>\n <button class=\"login-modal-confirm\" id=\"login-modal-confirm\">退出登录<\/button>\n <\/div>\n <\/div>\n <\/div>\n\n <!-- 备注弹窗 -->\n <div class=\"remark-modal\" id=\"remark-modal\">\n <div class=\"remark-modal-content\">\n <div class=\"remark-modal-header\">\n <h3 class=\"remark-modal-title\">设置备注<\/h3>\n <button class=\"remark-modal-close\" id=\"remark-modal-close\">×<\/button>\n <\/div>\n <input type=\"text\" class=\"remark-modal-input\" id=\"remark-modal-input\" placeholder=\"输入备注\">\n <div class=\"remark-modal-actions\">\n <button class=\"remark-modal-cancel\" id=\"remark-modal-cancel\">取消<\/button>\n <button class=\"remark-modal-confirm\" id=\"remark-modal-confirm\">确认<\/button>\n <\/div>\n <\/div>\n <\/div>\n\n<\/body>\n<\/html>\n",
"startJs": "const m = \"https:\/\/m.weibo.cn\";\nconst mockData = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}');\n\n\/\/ 当前数据状态\nlet currentData = [...mockData.users];\nlet currentCategory = 'user';\nlet remarkItemId = null;\nlet searchHistory = JSON.parse(source.get('weiboSearchHistory') || '[]');\nlet selectedItemId = null;\nlet isSortMode = false;\n\njava.toast(\"加载cookie中...\");\nwindow.webViewAwait(\"\",\"https:\/\/m.weibo.cn\",\"document.cookie\")\n.then(r=>{\n\tif(\/MLOGIN=1\/.test(r)){\n\t\tjava.toast(\"cookie获取成功\")\n\t\t}else{\n\t\t\tjava.toast(\"cookie获取失败,可刷新重试,或者登录\")\n\t\t\t}\n\t})\n\t.catch(e=>console.log(e))\n\nfunction saveDataToJson() {\n switch(currentCategory) {\n case 'user':\n mockData.users = [...currentData];\n break;\n case 'topic':\n mockData.topics = [...currentData];\n break;\n case 'super':\n mockData.superTopics = [...currentData];\n break;\n }\n \n source.putVariable(JSON.stringify(mockData));\n}\n\nfunction handleItemClick(category, item) {\n let url,name;\n switch(category) {\n case 'user':\n name = \"👤\"+ (item.remarkName || item.name);\n url = m+\"\/api\/container\/getIndex?containerid=230413\"+item.id+\"_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&since_id=\"\n let userTopUrl = m+\"\/api\/container\/getIndex?type=uid&value=\"+ item.id;\n \n try{\n let userJsonData = java.ajax(userTopUrl);\n userJsonData = JSON.parse(userJsonData||\"{}\");\n if(userJsonData.ok===1){\n let tabsInfo = userJsonData.data.tabsInfo;\n let tabs = tabsInfo.tabs;\n let uu = {}\n let id = item.id;\n let base = m+\"\/api\/container\/getIndex?type=uid&value=\";\n uu[name+\"的微博\"] = url;\n tabs.forEach(x=>{\n switch(x.title){\n case \"精选\":\n url = base+id+\"&containerid=231002\"+id+\"_-_HOTMBLOG&page=1\"\n break;\n case \"视频\": \n case \"相册\":\n url = base+id+\"&containerid=\"+x.containerid+\"&since_id=\";\n break;\n }\n x.title!==\"微博\"? uu[x.title] = url:null\n });\n url = JSON.stringify(uu);\n }\n \n }catch(e){\n }\n \n \n break;\n case 'topic':\n name = \"💬\"+item.name;\n url = JSON.stringify({\n [name+\"的综合\"]: getHuatiUrl(1,item.name),\n \"实时\": getHuatiUrl(61,item.name),\n \"图片\": getHuatiUrl(63,item.name),\n \"视频\": getHuatiUrl(64,item.name),\n \"关注\": getHuatiUrl(62,item.name),\n \"热门\": getHuatiUrl(60,item.name),\n });\n break;\n case 'super':\n name = \"💎\"+item.name;\n url = `${m}\/api\/container\/getIndex?containerid=${item.id}_-_feed&since_id=`;\n url = getSuperUrl(name,url);\n break;\n \n }\n \n try{\n java.open(\"sort\", url,name);\n }catch(e){\n java.log(e)\n }\n}\n\n\nfunction getHuatiUrl(id,name){\n return `${m}\/api\/container\/getIndex?containerid=231522type%3D${id}%26t%3D10%26q%3D%23${name}%23&isnewpage=1&luicode=10000011&lfid=100103type%3D1%26q%3D${name}&page_type=searchall&page=1`;\n}\n\n\nfunction getSuperUrl(name,url){\n let jsonAjax = java.ajax(url);\n let jsonData = JSON.parse(jsonAjax);\n let channel_list = jsonData.data.pageInfo.cardlist_head_cards[0].channel_list;\n let data = {};\n channel_list.forEach(tab=>{\n let u = `${m}\/api\/container\/getIndex?containerid=`;\n if(tab.id == \"feed\"){\n data[name+\"的📝帖子\"] = u+tab.containerid+\"&since_id=\";\n data[\"📤帖子\"] = u+tab.containerid.replace(\/feed\/,'sort_time')+\"&since_id=\";\n data[\"🔥帖子\"] = u+tab.containerid.replace(\/feed\/,'recommend')+\"&since_id=\";\n data[\"💡帖子\"] = u+tab.containerid.replace(\/feed\/,'soul')+\"&since_id=\";\n }else if(\/\\d+\/.test(tab.id)){\n data[\"📝\"+tab.name] = u+tab.containerid+\"&since_id=\";\n data[\"📤\"+tab.name] = u+tab.containerid.replace(\/comment_sort\/,'status_sort')+\"&since_id=\";\n }else{\n data[tab.name] = u+tab.containerid+\"&since_id=\";\n }\n })\n \n return JSON.stringify(data)\n \n}\n\n\ndocument.addEventListener('DOMContentLoaded', function() {\n renderSubscribeContent(currentCategory);\n const categoryTabs = document.querySelectorAll('.category-tab');\n categoryTabs.forEach(tab => {\n tab.addEventListener('click', function() {\n categoryTabs.forEach(t => t.classList.remove('active'));\n this.classList.add('active');\n const category = this.getAttribute('data-category');\n currentCategory = category;\n switch(category) {\n case 'user':\n currentData = [...mockData.users];\n break;\n case 'topic':\n currentData = [...mockData.topics];\n break;\n case 'super':\n currentData = [...mockData.superTopics];\n break;\n }\n \n renderSubscribeContent(category);\n });\n });\n \n const searchBtn = document.querySelector('.search-btn');\n searchBtn.addEventListener('click', function() {\n const searchInput = document.querySelector('.search-box input');\n const searchText = searchInput.value.toLowerCase();\n \n const filteredData = currentData.filter(item => \n item.name.toLowerCase().includes(searchText) || \n item.desc.toLowerCase().includes(searchText)\n );\n \n renderSubscribeList(filteredData);\n });\n \n const bottomButtons = document.querySelectorAll('.bottom-button');\n bottomButtons.forEach(button => {\n button.addEventListener('click', function() {\n const type = this.getAttribute('data-type');\n handleBottomButtonClick(type);\n });\n });\n \n const searchModal = document.getElementById('search-modal');\n const searchModalClose = document.getElementById('search-modal-close');\n const searchModalCancel = document.getElementById('search-modal-cancel');\n const searchModalConfirm = document.getElementById('search-modal-confirm');\n const searchModalInput = document.getElementById('search-modal-input');\n const searchclear = document.getElementById(\"search-clear\")\n \n const loginModal = document.getElementById('login-modal');\n const loginModalClose = document.getElementById('login-modal-close');\n const loginModalCancel = document.getElementById('login-modal-cancel');\n const loginModalConfirm = document.getElementById('login-modal-confirm');\n \nclass WeiboFollowManager {\n constructor() {\n this.users = [];\n this.selectedUsers = new Set();\n this.currentPage = 0;\n this.nextCursor = 0;\n this.isLoading = false;\n }\n\n createPopup() {\n const popup = document.createElement('div');\n popup.id = 'weibo-follow-popup';\n popup.style.cssText = `\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 90%;\n max-width: 800px;\n max-height: 80vh;\n background: white;\n border-radius: 12px;\n box-shadow: 0 10px 30px rgba(0,0,0,0.3);\n z-index: 10000;\n display: none;\n flex-direction: column;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n `;\n\n const header = document.createElement('div');\n header.style.cssText = `\n padding: 20px;\n background: linear-gradient(135deg, #ff8200, #ff4500);\n color: white;\n display: flex;\n justify-content: space-between;\n align-items: center;\n `;\n \n const title = document.createElement('h3');\n title.textContent = '我的关注';\n title.style.margin = '0';\n title.style.fontSize = '18px';\n \n const closeBtn = document.createElement('button');\n closeBtn.textContent = '×';\n closeBtn.style.cssText = `\n background: none;\n border: none;\n color: white;\n font-size: 24px;\n cursor: pointer;\n padding: 0 10px;\n line-height: 1;\n `;\n closeBtn.onclick = () => this.hidePopup();\n \n header.appendChild(title);\n header.appendChild(closeBtn);\n \n const controls = document.createElement('div');\n controls.style.cssText = `\n padding: 12px 20px;\n background: #f8f9fa;\n border-bottom: 1px solid #e9ecef;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n `;\n \n const leftControls = document.createElement('div');\n leftControls.style.display = 'flex';\n leftControls.style.gap = '8px';\n leftControls.style.flexWrap = 'wrap';\n \n const selectAllBtn = document.createElement('button');\n selectAllBtn.textContent = '全选';\n selectAllBtn.className = 'control-btn';\n \n const deselectAllBtn = document.createElement('button');\n deselectAllBtn.textContent = '取消全选';\n deselectAllBtn.className = 'control-btn';\n \n const batchSubscribeBtn = document.createElement('button');\n batchSubscribeBtn.textContent = '批量订阅';\n batchSubscribeBtn.className = 'control-btn batch-subscribe';\n batchSubscribeBtn.disabled = true;\n \n leftControls.appendChild(selectAllBtn);\n leftControls.appendChild(deselectAllBtn);\n leftControls.appendChild(batchSubscribeBtn);\n \n const rightControls = document.createElement('div');\n rightControls.style.display = 'flex';\n rightControls.style.alignItems = 'center';\n rightControls.style.gap = '10px';\n \n const searchInput = document.createElement('input');\n searchInput.type = 'text';\n searchInput.placeholder = '搜索用户...';\n searchInput.style.cssText = `\n padding: 6px 12px;\n border: 1px solid #ddd;\n border-radius: 6px;\n font-size: 13px;\n width: 150px;\n `;\n searchInput.oninput = (e) => this.filterUsers(e.target.value);\n \n rightControls.appendChild(searchInput);\n \n controls.appendChild(leftControls);\n controls.appendChild(rightControls);\n \n const listContainer = document.createElement('div');\n listContainer.id = 'follow-list-container';\n listContainer.style.cssText = `\n flex: 1;\n overflow-y: auto;\n padding: 15px;\n `;\n \n const loadingDiv = document.createElement('div');\n loadingDiv.id = 'loading-indicator';\n loadingDiv.style.cssText = `\n text-align: center;\n padding: 40px 20px;\n color: #666;\n display: none;\n `;\n loadingDiv.innerHTML = `\n <div style=\"margin-bottom: 10px;\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 50 50\">\n <path fill=\"#ff8200\" d=\"M25,5A20.14,20.14,0,0,1,45,22.88a2.51,2.51,0,0,0,2.49,2.26h0A2.52,2.52,0,0,0,50,22.33a25.14,25.14,0,0,0-50,0,2.52,2.52,0,0,0,2.5,2.81h0A2.51,2.51,0,0,0,5,22.88,20.14,20.14,0,0,1,25,5Z\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\" dur=\"0.5s\" repeatCount=\"indefinite\"\/>\n <\/path>\n <\/svg>\n <\/div>\n <div>正在加载关注列表...<\/div>\n `;\n \n const emptyState = document.createElement('div');\n emptyState.id = 'empty-state';\n emptyState.style.cssText = `\n text-align: center;\n padding: 40px 20px;\n color: #999;\n display: none;\n `;\n emptyState.innerHTML = `\n <div style=\"font-size: 48px; margin-bottom: 20px;\">👥<\/div>\n <div style=\"font-size: 16px; margin-bottom: 10px;\">暂无关注用户<\/div>\n <div style=\"font-size: 14px; color: #666;\">您还没有关注任何用户<\/div>\n `;\n \n const footer = document.createElement('div');\n footer.style.cssText = `\n padding: 12px 20px;\n background: #f8f9fa;\n border-top: 1px solid #e9ecef;\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: #666;\n font-size: 13px;\n `;\n \n const statusText = document.createElement('span');\n statusText.id = 'status-text';\n statusText.textContent = '已选择 0 个用户';\n \n const actionButtons = document.createElement('div');\n actionButtons.style.display = 'flex';\n actionButtons.style.gap = '8px';\n actionButtons.style.flexWrap = 'wrap';\n \n const closeButton = document.createElement('button');\n closeButton.textContent = '关闭';\n closeButton.className = 'control-btn secondary';\n closeButton.onclick = () => this.hidePopup();\n \n const loadMoreBtn = document.createElement('button');\n loadMoreBtn.textContent = '加载更多';\n loadMoreBtn.className = 'control-btn';\n loadMoreBtn.id = 'load-more-btn';\n loadMoreBtn.style.display = 'none';\n \n actionButtons.appendChild(loadMoreBtn);\n actionButtons.appendChild(closeButton);\n \n footer.appendChild(statusText);\n footer.appendChild(actionButtons);\n \n popup.appendChild(header);\n popup.appendChild(controls);\n popup.appendChild(loadingDiv);\n popup.appendChild(emptyState);\n popup.appendChild(listContainer);\n popup.appendChild(footer);\n \n const overlay = document.createElement('div');\n overlay.id = 'weibo-follow-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9999;\n display: none;\n `;\n overlay.onclick = () => this.hidePopup();\n \n document.body.appendChild(overlay);\n document.body.appendChild(popup);\n \n this.addStyles();\n \n selectAllBtn.onclick = () => this.selectAllUsers();\n deselectAllBtn.onclick = () => this.deselectAllUsers();\n batchSubscribeBtn.onclick = () => this.batchSubscribe();\n loadMoreBtn.onclick = () => this.loadMore();\n \n return popup;\n }\n \n addStyles() {\n const style = document.createElement('style');\n style.textContent = `\n .control-btn {\n padding: 6px 12px;\n border: none;\n border-radius: 6px;\n background: #ff8200;\n color: white;\n cursor: pointer;\n font-size: 13px;\n transition: all 0.2s;\n font-weight: 500;\n }\n \n .control-btn:hover:not(:disabled) {\n background: #ff6a00;\n transform: translateY(-1px);\n box-shadow: 0 2px 5px rgba(255, 106, 0, 0.3);\n }\n \n .control-btn:active:not(:disabled) {\n transform: translateY(0);\n }\n \n .control-btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n \n .control-btn.secondary {\n background: #6c757d;\n }\n \n .control-btn.secondary:hover {\n background: #545b62;\n box-shadow: 0 2px 5px rgba(108, 117, 125, 0.3);\n }\n \n .batch-subscribe {\n background: #28a745;\n }\n \n .batch-subscribe:hover:not(:disabled) {\n background: #218838;\n box-shadow: 0 2px 5px rgba(40, 167, 69, 0.3);\n }\n \n .user-item {\n display: flex;\n align-items: center;\n padding: 12px;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n background: white;\n }\n \n .user-item:hover {\n border-color: #ff8200;\n box-shadow: 0 2px 8px rgba(255, 130, 0, 0.1);\n transform: translateY(-1px);\n }\n \n .user-item.selected {\n border-color: #28a745;\n background-color: rgba(40, 167, 69, 0.05);\n }\n \n .user-checkbox {\n margin-right: 12px;\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: #ff8200;\n }\n \n .user-avatar {\n width: 45px;\n height: 45px;\n border-radius: 50%;\n object-fit: cover;\n margin-right: 12px;\n border: 2px solid #f0f0f0;\n }\n \n .user-info {\n flex: 1;\n min-width: 0;\n }\n \n .user-name {\n font-weight: 600;\n margin: 0 0 4px 0;\n color: #333;\n font-size: 15px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n \n \n \n .user-followers {\n font-size: 12px;\n color: #666;\n margin: 0 0 3px 0;\n white-space: normal; \/* 允许换行 *\/\n word-break: break-all; \/* 允许在任意字符间断行 *\/\n overflow-wrap: break-word; \/* 长单词或URL可以中断并换行 *\/\n line-height: 1.4; \/* 增加行高,使多行文本更易读 *\/\n}\n.user-remark{\n color:green\n}\n \n .subscribe-btn {\n padding: 5px 10px;\n background: #ff8200;\n color: white;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.2s;\n font-weight: 500;\n white-space: nowrap;\n margin-left: 8px;\n }\n \n .subscribe-btn:hover {\n background: #ff6a00;\n transform: translateY(-1px);\n box-shadow: 0 2px 5px rgba(255, 106, 0, 0.3);\n }\n \n .subscribe-btn.subscribed {\n background: #28a745;\n }\n \n .subscribe-btn.subscribed:hover {\n background: #218838;\n box-shadow: 0 2px 5px rgba(40, 167, 69, 0.3);\n }\n \n #weibo-follow-popup {\n animation: popupFadeIn 0.3s ease;\n }\n \n #weibo-follow-overlay {\n animation: overlayFadeIn 0.3s ease;\n }\n \n @keyframes popupFadeIn {\n from {\n opacity: 0;\n transform: translate(-50%, -60%);\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n }\n \n @keyframes overlayFadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n \n \/* 滚动条样式 *\/\n #follow-list-container::-webkit-scrollbar {\n width: 6px;\n }\n \n #follow-list-container::-webkit-scrollbar-track {\n background: #f1f1f1;\n border-radius: 3px;\n }\n \n #follow-list-container::-webkit-scrollbar-thumb {\n background: #ccc;\n border-radius: 3px;\n }\n \n #follow-list-container::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n }\n `;\n document.head.appendChild(style);\n }\n \n async showPopup() {\n let overlay = document.getElementById('weibo-follow-overlay');\n let popup = document.getElementById('weibo-follow-popup');\n \n if (!popup || !overlay) {\n popup = this.createPopup();\n overlay = document.getElementById('weibo-follow-overlay');\n }\n \n overlay.style.display = 'block';\n popup.style.display = 'flex';\n document.body.style.overflow = 'hidden';\n \n this.users = [];\n this.selectedUsers.clear();\n this.currentPage = 0;\n this.nextCursor = 0;\n \n const listContainer = document.getElementById('follow-list-container');\n const emptyState = document.getElementById('empty-state');\n const loadingDiv = document.getElementById('loading-indicator');\n \n listContainer.innerHTML = '';\n emptyState.style.display = 'none';\n \n await this.loadFollowList();\n }\n \n hidePopup() {\n const overlay = document.getElementById('weibo-follow-overlay');\n const popup = document.getElementById('weibo-follow-popup');\n \n if (overlay) overlay.style.display = 'none';\n if (popup) popup.style.display = 'none';\n \n document.body.style.overflow = '';\n }\n \n async loadFollowList() {\n if (this.isLoading) return;\n \n this.isLoading = true;\n const loadingDiv = document.getElementById('loading-indicator');\n const listContainer = document.getElementById('follow-list-container');\n const emptyState = document.getElementById('empty-state');\n const loadMoreBtn = document.getElementById('load-more-btn');\n \n loadingDiv.style.display = 'block';\n loadMoreBtn.style.display = 'none';\n \n try {\n let pp = 0;\n while(++pp){\n const url = `https:\/\/m.weibo.cn\/api\/container\/getIndex?containerid=231093_-_selffollowed&page=${pp+this.currentPage}`;\n const response = await fetch(url, {\n credentials: 'include' \n });\n if (!response.ok) {\n throw new Error(`HTTP错误! 状态码: ${response.status}`);\n }\n let data = await response.json();\n \n \n if (data.ok !== 1) {\n throw new Error('API返回错误: ' + (data.msg || '未知错误'));\n }\n \n data.data.cards.forEach(cards => {\n (cards?.card_group??[]).forEach(u=>{\n if(u.user){\n let x = u.user;\n const user = {\n id: String(x.id),\n name: x.screen_name || '未知用户',\n remarkName:x.remark || \"\",\n avatar: x.avatar_hd || x.avatar_large || '',\n desc: `粉丝:${x.followers_count_str || '0'}${x.description?\"<br>\"+x.description:\"\"}`,\n isSubscribed: this.checkIfSubscribed(String(x.id)) \n };\n this.users.push(user);\n }\n })\n });\n this.nextCursor = data.data.cardlistInfo.page || 0;\n if(this.nextCursor == 0 || pp>=5){\n break\n }\n }\n \n this.renderUserList();\n this.updateStatus();\n \n if (this.users.length === 0) {\n emptyState.style.display = 'block';\n } else {\n emptyState.style.display = 'none';\n }\n \n if (this.nextCursor !== 0) {\n loadMoreBtn.style.display = 'block';\n }\n \n } catch (error) {\n console.error('加载关注列表失败:', error);\n \n const errorDiv = document.createElement('div');\n errorDiv.style.cssText = `\n text-align: center;\n padding: 40px 20px;\n color: #dc3545;\n `;\n errorDiv.innerHTML = `\n <div style=\"font-size: 48px; margin-bottom: 20px;\">⚠️<\/div>\n <div style=\"font-size: 16px; margin-bottom: 10px;\">加载失败<\/div>\n <div style=\"font-size: 14px; margin-bottom: 20px; color: #666;\">${error.message}<\/div>\n <button onclick=\"window.weiboFollowManager.retryLoad()\" class=\"control-btn\">重试<\/button>\n `;\n \n listContainer.innerHTML = '';\n listContainer.appendChild(errorDiv);\n \n } finally {\n this.isLoading = false;\n loadingDiv.style.display = 'none';\n }\n }\n \n retryLoad() {\n const listContainer = document.getElementById('follow-list-container');\n listContainer.innerHTML = '';\n this.currentPage = 0;\n this.nextCursor = 0;\n this.users = [];\n this.loadFollowList();\n }\n \n async loadMore() {\n this.currentPage += 5;\n await this.loadFollowList();\n }\n \n filterUsers(keyword) {\n const listContainer = document.getElementById('follow-list-container');\n const userItems = listContainer.querySelectorAll('.user-item');\n \n if (!keyword.trim()) {\n userItems.forEach(item => {\n item.style.display = 'flex';\n });\n return;\n }\n \n const searchTerm = keyword.toLowerCase();\n userItems.forEach(item => {\n const name = item.querySelector('.user-name').textContent.toLowerCase();\n const remark = item.querySelector('.user-remark')\n const remarkName = remark?remark.textContent.toLowerCase():\"\";\n \n if (name.includes(searchTerm) || remarkName.includes(searchTerm)) {\n item.style.display = 'flex';\n } else {\n item.style.display = 'none';\n }\n });\n }\n \n renderUserList() {\n const listContainer = document.getElementById('follow-list-container');\n \n this.users.forEach((user, index) => {\n if (document.getElementById(`user-${user.id}`)) {\n return;\n }\n \n const userItem = document.createElement('div');\n userItem.id = `user-${user.id}`;\n userItem.className = 'user-item';\n userItem.dataset.index = index;\n \n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.className = 'user-checkbox';\n checkbox.checked = this.selectedUsers.has(user.id);\n checkbox.onchange = (e) => {\n e.stopPropagation();\n this.toggleUserSelection(user.id, checkbox.checked);\n };\n const avatar = document.createElement('img');\n avatar.className = 'user-avatar';\n avatar.src = user.avatar;\n avatar.alt = user.name;\n avatar.onerror = () => {\n avatar.src = 'data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIyMCIgY3k9IjIwIiByPSIyMCIgZmlsbD0iI0YwRjBGMCIvPjxwYXRoIGQ9Ik0yNiAyN0MxOCAyNyAxNSAzMiAxNSAzMkgxNUMxNSAzMiAxNiAyOCAyMCAyOEMyNCAyOCAyNSAzMiAyNSAzMkgyNUMxNSAzMiAyNyAyNyAyNiAyN1oiIGZpbGw9IiNDQ0NDQ0MiLz48Y2lyY2xlIGN4PSIyMCIgY3k9IjE2IiByPSI1IiBmaWxsPSIjQ0NDQ0NDIi8+PC9zdmc+';\n };\n \n const userInfo = document.createElement('div');\n userInfo.className = 'user-info';\n \n const userName = document.createElement('div');\n userName.className = 'user-name';\n userName.textContent = user.name;\n userName.title = user.name;\n \n \n let remarkName = \"\";\n \n if(user.remarkName){\n remarkName = document.createElement('p');\n remarkName.className = 'user-remark';\n remarkName.textContent = \"备注: \"+ user.remarkName;\n }\n \n \n const userFollowers = document.createElement('div');\n userFollowers.className = 'user-followers';\n userFollowers.innerHTML = (remarkName?remarkName.outerHTML : \"\")\n + user.desc;\n \n userInfo.appendChild(userName);\n userInfo.appendChild(userFollowers);\n const subscribeBtn = document.createElement('button');\n subscribeBtn.className = `subscribe-btn ${user.isSubscribed ? 'subscribed' : ''}`;\n subscribeBtn.textContent = user.isSubscribed ? '已订阅' : '订阅';\n subscribeBtn.onclick = (e) => {\n e.stopPropagation();\n this.subscribeUser(user,'0');\n subscribeBtn.textContent = '已订阅';\n subscribeBtn.className = 'subscribe-btn subscribed';\n user.isSubscribed = true;\n };\n \n userItem.appendChild(checkbox);\n userItem.appendChild(avatar);\n userItem.appendChild(userInfo);\n userItem.appendChild(subscribeBtn);\n userItem.onclick = (e) => {\n if (e.target !== checkbox && e.target !== subscribeBtn) {\n checkbox.checked = !checkbox.checked;\n this.toggleUserSelection(user.id, checkbox.checked);\n }\n };\n \n listContainer.appendChild(userItem);\n });\n }\n \n checkIfSubscribed(userId) {\n \n let subscribedUsers = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}').users;\n \n return subscribedUsers.some(user => \n user && user.id && String(user.id) === String(userId)\n );\n }\n \n toggleUserSelection(userId, isSelected) {\n if (isSelected) {\n this.selectedUsers.add(userId);\n const checkbox = document.querySelector(`#user-${userId} .user-checkbox`);\n if (checkbox) {\n checkbox.checked = true;\n }\n const userItem = document.getElementById(`user-${userId}`);\n if (userItem) {\n userItem.classList.add('selected');\n }\n } else {\n this.selectedUsers.delete(userId);\n const checkbox = document.querySelector(`#user-${userId} .user-checkbox`);\n if (checkbox) {\n checkbox.checked = false;\n }\n const userItem = document.getElementById(`user-${userId}`);\n if (userItem) {\n userItem.classList.remove('selected');\n }\n }\n \n this.updateStatus();\n }\n \n selectAllUsers() {\n this.users.forEach(user => {\n this.selectedUsers.add(user.id);\n const checkbox = document.querySelector(`#user-${user.id} .user-checkbox`);\n if (checkbox) {\n checkbox.checked = true;\n }\n const userItem = document.getElementById(`user-${user.id}`);\n if (userItem) {\n userItem.classList.add('selected');\n }\n });\n this.updateStatus();\n }\n \n deselectAllUsers() {\n this.selectedUsers.clear();\n document.querySelectorAll('.user-checkbox').forEach(checkbox => {\n checkbox.checked = false;\n });\n document.querySelectorAll('.user-item').forEach(item => {\n item.classList.remove('selected');\n });\n this.updateStatus();\n }\n \n updateStatus() {\n const statusText = document.getElementById('status-text');\n const batchBtn = document.querySelector('.batch-subscribe');\n \n if (statusText) {\n const total = this.users.length;\n const selected = this.selectedUsers.size;\n statusText.textContent = `已选择 ${selected} 个用户,共 ${total} 个`;\n }\n \n if (batchBtn) {\n batchBtn.disabled = this.selectedUsers.size === 0;\n }\n }\n \n subscribeUser(user,type) {\n let jsonData = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}');\n let existingUser = jsonData[\"users\"].find(u => String(u.id) === user.id);\n if (!existingUser) {\n jsonData[\"users\"].push(user);\n source.putVariable(JSON.stringify(jsonData))\n }\n if(type==='0')this.showToast(`已订阅用户: ${user.name}`);\n currentData = JSON.parse(source.getVariable() || '{\"users\":[],\"topics\":[],\"superTopics\":[]}').users;\n renderSubscribeList(currentData);\n }\n \n batchSubscribe() {\n if (this.selectedUsers.size === 0) {\n this.showToast('请先选择要订阅的用户');\n return;\n }\n \n const userIds = Array.from(this.selectedUsers);\n const userNames = userIds.map(id => {\n const user = this.users.find(u => u.id === id);\n return user ? user.name : '未知用户';\n }).slice(0, 3); \n \n const confirmMsg = userIds.length <= 3 \n ? `确定要订阅以下用户吗?\\n${userNames.join('\\n')}`\n : `确定要订阅选中的 ${userIds.length} 个用户吗?\\n包括:${userNames.join('、')}等`;\n \n if (confirm(confirmMsg)) {\n userIds.forEach(userId => {\n const userItem = document.getElementById(`user-${userId}`);\n if (userItem) {\n const btn = userItem.querySelector('.subscribe-btn');\n if (btn) {\n btn.textContent = '已订阅';\n btn.className = 'subscribe-btn subscribed';\n }\n }\n });\n \n this.showToast(`成功订阅了 ${userIds.length} 个用户!`);\n \n userIds.forEach(id => {\n const user = this.users.find(u => u.id === id);\n if(user){\n this.subscribeUser(user);\n }\n })\n \n this.deselectAllUsers();\n }\n }\n \n showToast(message) {\n const oldToast = document.getElementById('weibo-toast');\n if (oldToast) {\n document.body.removeChild(oldToast);\n }\n \n const toast = document.createElement('div');\n toast.id = 'weibo-toast';\n toast.textContent = message;\n toast.style.cssText = `\n position: fixed;\n bottom: 50px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 12px 24px;\n border-radius: 6px;\n font-size: 14px;\n z-index: 10001;\n animation: toastFadeInOut 2s ease;\n `;\n \n const style = document.createElement('style');\n style.textContent = `\n @keyframes toastFadeInOut {\n 0% { opacity: 0; transform: translate(-50%, 20px); }\n 20% { opacity: 1; transform: translate(-50%, 0); }\n 80% { opacity: 1; transform: translate(-50%, 0); }\n 100% { opacity: 0; transform: translate(-50%, -20px); }\n }\n `;\n document.head.appendChild(style);\n \n document.body.appendChild(toast);\n \n setTimeout(() => {\n if (toast.parentNode) {\n document.body.removeChild(toast);\n }\n if (style.parentNode) {\n document.head.removeChild(style);\n }\n }, 2000);\n }\n \n}\n\n const manager = new WeiboFollowManager();\n const myFollowBtn = document.getElementById('login-modal-my');\n \n if (myFollowBtn) {\n myFollowBtn.addEventListener('click', (e) => {\n \n e.preventDefault();\n e.stopPropagation();\n manager.showPopup();\n closeModal();\n });\n } \n \n searchModalClose.addEventListener('click', closeModal);\n loginModalClose.addEventListener('click', closeModal);\n searchModalCancel.addEventListener('click', closeModal);\n \n searchModalConfirm.addEventListener('click', function() {\n const searchText = searchModalInput.value.trim();\n if (searchText) {\n addToSearchHistory(searchText);\n java.open(\"sort\",JSON.stringify({\"综合\":`${getSearchUrl(1,searchText)}`,\"关注\":`${getSearchUrl(62,searchText)}`,\"热门\":`${getSearchUrl(60,searchText)}`,\"实时\":`${getSearchUrl(61,searchText)}`,\"用户\":`${getSearchUrl(3,searchText)}`,\"视频\":`${getSearchUrl(64,searchText)}`,\"图片\":`${getSearchUrl(63,searchText)}`,\"话题\":`${getSearchUrl(38,searchText)}`,\"超话\":`${getSearchUrl(98,searchText)}`}));\n closeModal();\n }\n });\n \n loginModal.addEventListener('click', function(e) {\n closeModal();\n });\n \n loginModalConfirm.addEventListener('click', function() {\n java.toast(\"请稍候....\");\n run('cookie.removeCookie(\"https:\/\/m.weibo.cn#微博整合\")').then(r=>console.log('已退出登录'))\n webViewAwait(\"\",\"https:\/\/m.weibo.cn\/logout\",\"if(String(document.cookie.includes('MLOGIN=0'))){'已退出登录'}\") .then(r=>{\n alert(r);\n })\n .catch(e=>alert(\"执行出错:\"+e));\n });\n \n loginModalCancel.addEventListener('click', function() {\n setTimeout(function() {\n run('java.startBrowser(\"http:\/\/weibo.com\",\"电脑端登录\")');\n },8);\n \n setTimeout(function() {\n run('java.startBrowser(\"http:\/\/m.weibo.cn\",\"手机端登录\")');\n },20);\n \n closeModal();\n });\n \n const remarkModal = document.getElementById('remark-modal');\n const remarkModalClose = document.getElementById('remark-modal-close');\n const remarkModalCancel = document.getElementById('remark-modal-cancel');\n const remarkModalConfirm = document.getElementById('remark-modal-confirm');\n const remarkModalInput = document.getElementById('remark-modal-input');\n \n remarkModalClose.addEventListener('click', closeRemarkModal);\n remarkModalCancel.addEventListener('click', closeRemarkModal);\n remarkModalConfirm.addEventListener('click', function() {\n const remarkText = remarkModalInput.value.trim();\n if (remarkItemId) {\n updateRemarkName(remarkItemId, remarkText);\n closeRemarkModal();\n }\n });\n \n const contentArea = document.querySelector('.content-area');\n let startX = 0;\n let endX = 0;\n \n contentArea.addEventListener('touchstart', function(e) {\n startX = e.touches[0].clientX;\n }, { passive: true });\n \n contentArea.addEventListener('touchmove', function(e) {\n const currentX = e.touches[0].clientX;\n const diffX = currentX - startX;\n }, { passive: false });\n \n contentArea.addEventListener('touchend', function(e) {\n const endX = e.changedTouches[0].clientX;\n const diffX = endX - startX;\n const threshold = 50; \n \n if (Math.abs(diffX) > threshold) {\n const currentTab = document.querySelector('.category-tab.active');\n const tabs = Array.from(document.querySelectorAll('.category-tab'));\n const currentIndex = tabs.indexOf(currentTab);\n \n if (diffX > 0 && currentIndex > 0) {\n tabs[currentIndex - 1].click();\n } else if (diffX < 0 && currentIndex < tabs.length - 1) {\n tabs[currentIndex + 1].click();\n }\n }\n }, { passive: true });\n});\n\nfunction getHotUrl(type){\n return `${m}\/api\/container\/getIndex?containerid=${encodeURIComponent(\"106003type=25&t=3&disable_hot=1&filter_type=\"+type)}&title=微博热搜&show_cache_when_error=1&extparam=${encodeURIComponent(\"seat=1&lcate=1001&mi_cid=100103&filter_type=realtimehot&pos=0_0&c_type=30®ion_relas_conf=0&dgr=0&cate=10103&display_time=\"+parseInt(Date.now()\/1000)+\"&pre_seqid=\"+Date.now()+\"020423224\")}`;\n}\n\nfunction getSearchUrl(t,k){\n return `${m}\/api\/container\/getIndex?containerid=100103type%3D${t}%26q%3D${k}%26t%3D&page_type=searchall&page=1`;\n}\n\n\/\/ 渲染订阅内容\nfunction renderSubscribeContent(category) {\n let data = [];\n \n if (category === 'user') {\n data = [...mockData.users];\n } else if (category === 'topic') {\n data = [...mockData.topics];\n } else if (category === 'super') {\n data = [...mockData.superTopics];\n }\n renderSubscribeList(data);\n}\n\n\/\/ 渲染订阅列表\nfunction renderSubscribeList(data) {\n const subscribeList = document.getElementById('subscribe-list');\n subscribeList.innerHTML = '';\n \n data.forEach((item, index) => {\n const subscribeItem = document.createElement('div');\n subscribeItem.className = 'subscribe-item';\n subscribeItem.setAttribute('data-id', item.id);\n subscribeItem.setAttribute('data-index', index);\n const avatarContent = item.avatar ? \n `<img src=\"${item.avatar}\" alt=\"${item.name}\">` : \n item.name.charAt(0);\n \n const displayName = item.remarkName ?(item.name + \" (\"+item.remarkName+\")\"):item.name;\n \n subscribeItem.innerHTML = `\n <div class=\"subscribe-avatar\">${avatarContent}<\/div>\n <div class=\"subscribe-details\">\n <div class=\"subscribe-title\">${displayName}<\/div>\n <div class=\"subscribe-desc\">${item.desc}<\/div>\n <\/div>\n <div class=\"subscribe-actions\">\n <button class=\"subscribe-action delete\" data-action=\"delete\" title=\"删除\">❎<\/button>\n <button class=\"subscribe-action remark\" data-action=\"remark\" title=\"设置备注\">🆔<\/button>\n <button class=\"subscribe-action sort\" data-action=\"sort\" title=\"排序\">↕️<\/button>\n <\/div>\n `;\n \n if (isSortMode) {\n const swapButton = document.createElement('button');\n swapButton.className = 'subscribe-action swap';\n swapButton.setAttribute('data-action', 'swap');\n swapButton.setAttribute('title', '交换位置');\n swapButton.textContent = '⇄';\n subscribeItem.querySelector('.subscribe-actions').appendChild(swapButton);\n \n if (item.id === selectedItemId) {\n subscribeItem.classList.add('selected');\n }\n }\n \n subscribeList.appendChild(subscribeItem);\n });\n \n bindSubscribeActions();\n if (!isSortMode) {\n bindItemClickEvents();\n }\n}\n\nfunction bindItemClickEvents() {\n const subscribeItems = document.querySelectorAll('.subscribe-item');\n \n subscribeItems.forEach(item => {\n item.addEventListener('click', function(e) {\n if (e.target.classList.contains('subscribe-action')) {\n return;\n }\n \n const itemId = this.getAttribute('data-id');\n const currentItem = currentData.find(item => item.id === itemId);\n \n if (currentItem) {\n handleItemClick(currentCategory, currentItem);\n }\n });\n });\n}\n\nfunction bindSubscribeActions() {\n const deleteButtons = document.querySelectorAll('.subscribe-action.delete');\n const remarkButtons = document.querySelectorAll('.subscribe-action.remark');\n const sortButtons = document.querySelectorAll('.subscribe-action.sort');\n const swapButtons = document.querySelectorAll('.subscribe-action.swap');\n const subscribeItems = document.querySelectorAll('.subscribe-item');\n deleteButtons.forEach(button => {\n button.addEventListener('click', function(e) {\n e.stopPropagation();\n const itemElement = this.closest('.subscribe-item');\n const itemId = itemElement.getAttribute('data-id')\n if (confirm('确定要删除这个订阅吗?')) {\n deleteSubscribeItem(itemId);\n }\n });\n });\n \n remarkButtons.forEach(button => {\n button.addEventListener('click', function(e) {\n e.stopPropagation();\n const itemElement = this.closest('.subscribe-item');\n const itemId = itemElement.getAttribute('data-id');\n const currentName = itemElement.querySelector('.subscribe-title').textContent\n \n openRemarkModal(itemId, currentName);\n });\n });\n \n sortButtons.forEach(button => {\n button.addEventListener('click', function(e) {\n e.stopPropagation();\n toggleSortMode();\n });\n });\n \n swapButtons.forEach(button => {\n button.addEventListener('click', function(e) {\n e.stopPropagation();\n const itemElement = this.closest('.subscribe-item');\n const itemId = itemElement.getAttribute('data-id');\n \n \/\/handleSwapItem(itemId);\n handleInsertBefore(itemId)\n });\n });\n \n if (isSortMode) {\n subscribeItems.forEach(item => {\n item.addEventListener('click', function(e) {\n if (e.target.classList.contains('subscribe-action')) return;\n \n const itemId = this.getAttribute('data-id');\n handleSelectItem(itemId);\n });\n });\n }\n}\n\nfunction handleInsertBefore(targetItemId) {\n if (!isSortMode || !selectedItemId) {\n alert('请先选择要移动的项目');\n return;\n }\n\n if (selectedItemId === targetItemId) {\n alert('不能将项目插入到自己前面');\n return;\n }\n\n const selectedIndex = currentData.findIndex(item => item.id === selectedItemId);\n const targetIndex = currentData.findIndex(item => item.id === targetItemId);\n\n if (selectedIndex === -1 || targetIndex === -1) {\n alert('未找到所选项目或目标项目');\n return;\n }\n\n \/\/ 从数组中移除选中的项目\n const [removedItem] = currentData.splice(selectedIndex, 1);\n\n \/\/ 注意:移除后,目标索引可能会变化\n \/\/ 如果选中项原来在目标项前面,移除后目标项的索引会减1\n const newTargetIndex = currentData.findIndex(item => item.id === targetItemId);\n \n \/\/ 将项目插入到目标位置(前面)\n currentData.splice(newTargetIndex, 0, removedItem);\n\n selectedItemId = null; \/\/ 清除选中状态\n renderSubscribeList(currentData);\n saveDataToJson();\n}\n\n\n\n\nfunction toggleSortMode() {\n isSortMode = !isSortMode;\n selectedItemId = null;\n \n if (isSortMode) {\n alert('已进入排序模式,请先点击要移动的项目,再点击目标项目的交换按钮');\n } else {\n alert('已退出排序模式');\n }\n \n renderSubscribeList(currentData);\n}\n\nfunction handleSelectItem(itemId) {\n if (!isSortMode) return;\n \n selectedItemId = itemId;\n \n renderSubscribeList(currentData);\n}\n\nfunction handleSwapItem(targetItemId) {\n if (!isSortMode || !selectedItemId) {\n alert('请先选择要移动的项目');\n return;\n }\n \n if (selectedItemId === targetItemId) {\n alert('不能与自己交换位置');\n return;\n }\n \n const selectedIndex = currentData.findIndex(item => item.id === selectedItemId);\n const targetIndex = currentData.findIndex(item => item.id === targetItemId);\n \n if (selectedIndex === -1 || targetIndex === -1) return;\n \n [currentData[selectedIndex], currentData[targetIndex]] = \n [currentData[targetIndex], currentData[selectedIndex]];\n \n selectedItemId = null;\n renderSubscribeList(currentData);\n saveDataToJson();\n}\n\n\nfunction deleteSubscribeItem(itemId) {\n currentData = currentData.filter(item => item.id !== itemId);\n renderSubscribeList(currentData);\n saveDataToJson();\n}\n\nfunction openRemarkModal(itemId, currentName) {\n remarkItemId = itemId;\n const remarkModal = document.getElementById('remark-modal');\n const remarkModalInput = document.getElementById('remark-modal-input');\n \n remarkModalInput.value = currentName;\n remarkModal.classList.add('active');\n remarkModalInput.focus();\n}\n\nfunction closeRemarkModal() {\n const remarkModal = document.getElementById('remark-modal');\n const remarkModalInput = document.getElementById('remark-modal-input');\n \n remarkModal.classList.remove('active');\n remarkModalInput.value = '';\n remarkItemId = null;\n}\n\nfunction updateRemarkName(itemId, remarkName) {\n const itemIndex = currentData.findIndex(item => item.id === itemId);\n if (itemIndex !== -1) {\n currentData[itemIndex].remarkName = remarkName;\n }\n \n renderSubscribeList(currentData);\n saveDataToJson();\n}\n\nfunction handleBottomButtonClick(type) {\n switch (type) {\n case 'search':\n const searchModal = document.getElementById('search-modal');\n searchModal.classList.add('active');\n document.getElementById('search-modal-input').focus();\n renderSearchHistory();\n break;\n case 'hot':\n java.open(\"sort\", JSON.stringify({\"热搜\":`${getHotUrl(\"realtimehot\")}`,\"我的\":`${getHotUrl(\"mineband\")}`,\"社会\":`${getHotUrl(\"social\")}`,\"文娱\":`${getHotUrl(\"fun\")}`}),\"微博热搜\")\n break;\n case 'hotlist':\n java.open(\"sort\", JSON.stringify({\"热门\":`${m}\/api\/container\/getIndex?containerid=102803&since_id=0`,\"实时\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_8999_-_ctg1_8999_home&page=1`,\"榜单\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_600169_-_ctg1_600169&page=1`,\"同城\":`${m}\/api\/feed\/trendtop?containerid=102803_2222&page=1`,\"社会\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188&page=1`,\"科技\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_2088_-_ctg1_2088&page=1`,\"明星\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_4288_-_ctg1_4288&page=1`,\"电影\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_3288_-_ctg1_3288&page=1`,\"音乐\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_5288_-_ctg1_5288&page=1`,\"情感\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_1988_-_ctg1_1988&page=1`,\"时尚\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_4488_-_ctg1_4488&page=1`,\"美妆\":`${m}\/api\/feed\/trendtop?containerid=102803_ctg1_1588_-_ctg1_1588&page=1`}),\"微博热门\");\n break;\n case 'login':\n const loginModal = document.getElementById('login-modal');\n loginModal.classList.add('active');\n break;\n }\n}\n\nfunction renderSearchHistory() {\n const searchHistoryList = document.getElementById('search-history-list');\n searchHistoryList.innerHTML = '';\n \n if (searchHistory.length === 0) {\n searchHistoryList.innerHTML = '<div style=\"color: #999; font-size: 14px;\">暂无搜索历史<\/div>';\n return;\n }\n \n const recentHistory = searchHistory.slice(-10).reverse();\n \n recentHistory.forEach(item => {\n const historyItem = document.createElement('div');\n historyItem.className = 'search-history-item';\n historyItem.textContent = item;\n \n historyItem.addEventListener('click', function() {\n document.getElementById('search-modal-input').value = item;\n });\n \n searchHistoryList.appendChild(historyItem);\n });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n const clearButton = document.querySelector('.search-clear');\n if (clearButton) {\n clearButton.addEventListener('click', function() {\n source.put('weiboSearchHistory', '');\n searchHistory = [];\n renderSearchHistory()\n });\n }\n });\n\nfunction addToSearchHistory(searchText) {\n \n searchHistory = searchHistory.filter(item => item !== searchText);\n searchHistory.push(searchText);\n if (searchHistory.length > 50) {\n searchHistory = searchHistory.slice(-50);\n }\n source.put('weiboSearchHistory', JSON.stringify(searchHistory));\n}\n\nfunction closeModal() {\n document.getElementById('search-modal').classList.remove('active');\n document.getElementById('search-modal-input').value = '';\n document.getElementById('login-modal').classList.remove('active');\n}\n",
"startStyle": "* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n font-family: \"PingFang SC\", \"Microsoft YaHei\", sans-serif;\n }\n\n body {\n background-color: #f5f5f5;\n color: #333;\n line-height: 1.5;\n padding-bottom: 60px;\n }\n\n .container {\n max-width: 480px;\n margin: 0 auto;\n background-color: #fff;\n min-height: 100vh;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\n display: flex;\n flex-direction: column;\n }\n\n \/* 子选项区域 - 固定在顶部 *\/\n .sub-options {\n background-color: #f9f9f9;\n padding: 10px 15px;\n border-bottom: 1px solid #e6e6e6;\n position: sticky;\n top: 0;\n z-index: 10;\n box-shadow: 0 2px 5px rgba(0,0,0,0.1);\n }\n\n .category-tabs {\n display: flex;\n justify-content: center;\n margin-bottom: 10px;\n gap: 10px;\n }\n\n .category-tab {\n padding: 8px 15px;\n font-size: 12px;\n color: #666;\n cursor: pointer;\n border-radius: 15px;\n background-color: #fff;\n border: 1px solid #ddd;\n transition: all 0.3s ease;\n }\n\n .category-tab.active {\n background-color: #ff8200;\n color: white;\n border-color: #ff8200;\n }\n\n .category-tab:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n\n .search-box {\n display: flex;\n max-width: 400px;\n margin: 0 auto;\n }\n\n .search-box input {\n flex: 1;\n padding: 8px 10px;\n border: 1px solid #ddd;\n border-radius: 3px 0 0 3px;\n font-size: 12px;\n transition: border-color 0.3s;\n }\n\n .search-box input:focus {\n outline: none;\n border-color: #ff8200;\n }\n\n .search-btn {\n background-color: #ff8200;\n color: white;\n border: none;\n padding: 0 15px;\n border-radius: 0 3px 3px 0;\n cursor: pointer;\n transition: background-color 0.3s;\n }\n\n .search-btn:hover {\n background-color: #e67300;\n }\n\n \/* 内容区域 *\/\n .content-area {\n padding: 15px;\n flex: 1;\n overflow-y: auto;\n }\n \n \/* 底部按钮区域 *\/\n .bottom-buttons {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n background-color: #fff;\n border-top: 1px solid #e6e6e6;\n z-index: 100;\n box-shadow: 0 -2px 10px rgba(0,0,0,0.05);\n }\n \n .bottom-button {\n flex: 1;\n padding: 12px 5px;\n border: none;\n background: none;\n font-size: 12px;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n transition: all 0.3s;\n }\n \n .bottom-button:hover {\n background-color: #f5f5f5;\n }\n \n .bottom-button-icon {\n font-size: 14px;\n margin-bottom: 4px;\n }\n \n .bottom-button-text {\n font-size: 12px;\n }\n\n \/* 订阅列表 *\/\n .subscribe-list {\n margin-top: 15px;\n }\n\n .subscribe-item {\n display: flex;\n align-items: center;\n padding: 12px;\n background-color: #f9f9f9;\n border-radius: 8px;\n margin-bottom: 10px;\n transition: all 0.3s;\n box-shadow: 0 2px 3px rgba(0,0,0,0.1);\n }\n\n .subscribe-item:hover {\n border-left: 4px solid #ff7b00; \n margin-left: -4px; \n padding-left: 4px; \n box-shadow: 0 2px 10px rgba(0,0,0,0.15);\n }\n\n .subscribe-item.sort-mode {\n background-color: #f0f0f0;\n }\n\n .subscribe-item.selected {\n background-color: #ffe0b2;\n border: 2px solid #ff8200;\n }\n\n .subscribe-avatar {\n \n box-shadow: 0 2px 5px rgba(0,0,0,0.15);\n width: 40px;\n height: 40px;\n border-radius: 5px;\n background-color: #e6e6e6;\n margin-right: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n color: #999;\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .subscribe-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .subscribe-details {\n flex: 1;\n min-width: 0;\n }\n\n .subscribe-title {\n font-size: 12px;\n font-weight: 500;\n margin-bottom: 5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .subscribe-desc {\n font-size: 10px;\n color: #999;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n \/* 更新:功能按钮垂直排列 *\/\n .subscribe-actions {\n display: flex;\n flex-direction: column;\n gap: 5px;\n flex-shrink: 0;\n margin-left: 10px;\n }\n\n .subscribe-action {\n background:none;\n border:none;\n padding: 4px;\n font-size: 10px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n transition: all 0.3s;\n }\n\n .subscribe-action:hover {\n transform: scale(1.1);\n }\n\n .subscribe-action.delete {\n color: #ff3b30;\n \n }\n\n .subscribe-action.remark {\n color: #007aff;\n \n }\n\n .subscribe-action.sort {\n color: #34c759;\n \n }\n\n .subscribe-action.swap {\n color: #ff8200;\n \n }\n\n \/* 搜索弹窗 *\/\n .search-modal,.login-modal {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n align-items: center;\n justify-content: center;\n }\n\n .search-modal.active,.login-modal.active{\n display: flex;\n }\n\n .search-modal-content,.login-modal-content {\n background-color: #fff;\n width: 90%;\n max-width: 400px;\n border-radius: 12px;\n padding: 20px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n animation: modalSlideIn 0.3s ease;\n }\n\n @keyframes modalSlideIn {\n from { transform: translateY(-20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n\n .search-modal-header,.login-modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #e6e6e6;\n }\n\n .search-modal-title,.login-modal-title {\n font-size: 14px;\n font-weight: 600;\n }\n\n .search-modal-close,.login-modal-close {\n background: none;\n border: none;\n font-size: 16px;\n cursor: pointer;\n color: #999;\n transition: color 0.3s;\n }\n\n .search-modal-close:hover {\n color: #333;\n }\n\n .search-modal-input {\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n margin-bottom: 15px;\n transition: border-color 0.3s;\n }\n\n .search-modal-input:focus {\n outline: none;\n border-color: #ff8200;\n }\n\n .search-history {\n margin-bottom: 20px;\n }\n\/*\n .search-history-title {\n font-size: 14px;\n color: #666;\n margin-bottom: 10px;\n }\n *\/ \n .search-history-title {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 15px;\n border-bottom: 1px solid #f0f0f0;\n }\n .search-clear {\n background-color: #f0f0f0;\n color: #666;\n padding: 8px 15px;\n border-radius: 20px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 5px;\n }\n .search-clear:hover {\n background-color: #e0e0e0;\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n }\n .search-history-list {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .search-history-item {\n background-color: #f5f5f5;\n padding: 6px 12px;\n border-radius: 15px;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.3s;\n }\n\n .search-history-item:hover {\n background-color: #e6e6e6;\n }\n\n .search-modal-actions {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n }\n \n .login-modal-actions{\n justify-content: center;\n display: flex;\n gap: 10px;\n }\n \n .search-modal-cancel,.login-modal-cancel {\n background: none;\n border: 1px solid #ddd;\n padding: 10px 20px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.3s;\n }\n \n .login-modal-cancel{\n background-color: #ff8200;\n color: white;\n border: none;\n }\n \n .search-modal-cancel:hover {\n background-color: #f5f5f5;\n }\n\n .search-modal-confirm,.login-modal-confirm,.login-modal-my{\n background-color: #ff8200;\n color: white;\n border: none;\n padding: 10px 20px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background-color 0.3s;\n }\n \n .login-modal-confirm,.login-modal-my{\n background: none;\n border: 1px solid #ddd;\n color:#000\n }\n \n .search-modal-confirm:hover {\n background-color: #e67300;\n }\n\n \/* 备注弹窗 *\/\n .remark-modal {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n align-items: center;\n justify-content: center;\n }\n\n .remark-modal.active {\n display: flex;\n }\n\n .remark-modal-content {\n background-color: #fff;\n width: 80%;\n max-width: 400px;\n border-radius: 12px;\n padding: 20px;\n animation: modalSlideIn 0.3s ease;\n }\n\n .remark-modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #e6e6e6;\n }\n\n .remark-modal-title {\n font-size: 14px;\n font-weight: 600;\n }\n\n .remark-modal-close {\n background: none;\n border: none;\n font-size: 16px;\n cursor: pointer;\n color: #999;\n transition: color 0.3s;\n }\n\n .remark-modal-close:hover {\n color: #333;\n }\n\n .remark-modal-input {\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n margin-bottom: 15px;\n transition: border-color 0.3s;\n }\n\n .remark-modal-input:focus {\n outline: none;\n border-color: #ff8200;\n }\n\n .remark-modal-actions {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n }\n\n .remark-modal-cancel {\n background: none;\n border: 1px solid #ddd;\n padding: 10px 20px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.3s;\n }\n\n .remark-modal-cancel:hover {\n background-color: #f5f5f5;\n }\n\n .remark-modal-confirm {\n background-color: #ff8200;\n color: white;\n border: none;\n padding: 10px 20px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background-color 0.3s;\n }\n\n .remark-modal-confirm:hover {\n background-color: #e67300;\n }\n\n \/* 响应式设计 *\/\n @media (max-width: 480px) {\n .container {\n max-width: 100%;\n }\n \n .subscribe-action {\n width: 12px;\n height: 12px;\n font-size: 10px;\n }\n }\n\n @media (max-width: 360px) {\n .subscribe-actions {\n gap: 3px;\n }\n \n .subscribe-action {\n width: 12px;\n height: 12px;\n font-size: 10px;\n padding: 4px;\n }\n }",
"style": " * { margin: 0; padding: 0; box-sizing: border-box; }\n body { \n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif; \n line-height: 1.6; color: #333; background-color: #f5f5f5; \n padding: 15px; max-width: 750px; margin: 0 auto; \n width:100%\n }\n .original-links {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: 5px;\n box-sizing: border-box;\n margin-bottom:8px\n}\n\na.original-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 8px;\n background: #fff;\n border-radius: 8px;\n font-size: 13px;\n text-decoration: none;\n color: #1E88E5;\n font-weight: 500;\n box-shadow: 0 1px 3px rgba(0,0,0,0.05);\n width: 45%;\n text-align: center;\n}\n\n .main-content { \n background: #fff; padding: 15px; border-radius: 8px; \n margin-bottom: 15px; box-shadow: 0 1px 3px rgba(0,0,0,0.05); \n }\n .divider { border: none; height: 1px; background-color: #eee; margin: 15px 0; }\n .media-container { margin: 15px 0; border-radius: 8px; overflow: hidden; }\n .media-container video { width: 100%; border-radius: 8px; }\n .image-gallery { \n display: grid; \n grid-template-columns: repeat(3, 1fr); \n gap: 5px; \n margin: 5px 0; \n width:100%;\n z-index:999\n }\n \n .gallery-item { \n aspect-ratio: 1; overflow: hidden; border-radius: 8px; \n position: relative; cursor: pointer; \n }\n .gallery-item img { \n width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s; \n }\n .gallery-item:hover img { transform: scale(1.05); }\n \n .zoom-icon{ \n position: absolute; top: 5px; right: 5px; background: rgba(0,0,0,0.5); \n color: white; width: 30px; height: 20px; border-radius: 8%; \n display: flex; align-items: center; justify-content: center; \n font-size: 10px; opacity: 1; transition: opacity 0.3s; \n }\n .retweeted_status{\n background:#F7F7F7;\n padding:15px;\n border-radius:8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n }\n .comments-section { \n background: #fff; padding: 15px; border-radius: 8px; \n box-shadow: 0 1px 3px rgba(0,0,0,0.05); \n }\n .comment-replies{\n \tbackground:#F7F7F7;\n \tpadding:5px 5px 5px 20px;\n \tmargin-left:42px;\n \tborder-radius: 8px;\n \tbox-shadow: 0 1px 3px rgba(0,0,0,0.2);\n \t\n \t}\n \t\n.comments-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom:10px\n}\n\n.comments-title {\n margin: 0;\n font-size: 14px; \n color: #333; \n}\n\n.sort-controls {\n display: flex;\n align-items: center;\n}\n\n.sort-btn {\n padding: 4px 12px;\n border: 1px solid #e0e0e0;\n background: #f5f5f5;\n border-radius: 15px;\n font-size: 10px;\n cursor: pointer;\n margin-right: 8px; \n transition: all 0.3s;\n}\n\n\n.sort-btn:last-child {\n margin-right: 0;\n}\n\n.sort-btn.active {\n background: #1d9bf0;\n color: white;\n border-color: #1d9bf0;\n}\n\n \n .comment-item { padding: 12px 0; }\n \n .comment-user { display: flex; align-items: flex-start; margin-bottom: 8px; }\n .user-avatar { \n width: 32px;\n height: 32px;\n border-radius: 50%; \n \n \n margin-right: 10px; object-fit: cover; \n }\n .user-info {\n display: flex;\n flex-direction: column;\n}\n .user-name { \n font-weight: 500; \n font-size: 11px;\n color:#1E88E5\n }\n .remark{\n font-weight: 400; \n font-size: 8px;\n color:#888\n }\n .comment-text { \n margin-left: 42px;\n margin-bottom: 8px; font-size: 12px; line-height: 1.5; word-break: break-word; \n }\n .comment-time { font-size: 10px; color: #999; }\n .comment-media { \n margin-left:42px;\n margin-bottom:10px;\n margin-top:10px;\n margin-right:8px;\n position: relative; cursor: pointer; \n border-radius: 6px; overflow: hidden;\n max-width:100%\n }\n .comment-media details {\n margin: 8px 0;\n border-radius: 6px;\n overflow: hidden;\n }\n .comment-media summary {\n padding: 6px 12px;\n background: #f5f5f5;\n border-radius: 4px;\n cursor: pointer;\n list-style: none;\n font-size: 12px;\n color: #1E88E5;\n transition: background 0.2s;\n }\n .comment-media summary:hover {\n background: #e8f0fe;\n }\n .comment-media summary::-webkit-details-marker {\n display: none;\n }\n .comment-media div {\n margin-top: 8px;\n position: relative;\n cursor: pointer;\n }\n .comment-media img {\n max-width: 100%;\n border-radius: 4px;\n display: block;\n }\n.active {\n pointer-events: none; \n}\n\n .float-buttons {\n position: fixed;\n right: 20px;\n bottom: 20px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n z-index: 1001;\n }\n .reply-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0,0,0,0.5);\n z-index: 1000;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.modal-content {\n width: 80%;\n max-width: 600px;\n max-height: 80vh;\n background: white;\n border-radius: 8px;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.modal-body {\n flex: 1;\n overflow-y: auto;\n padding: 15px;\n}\n.modal-footer {\n padding: 10px;\n text-align: center;\n}\n.loading-spinner {\n display: none;\n width: 20px;\n height: 20px;\n border: 3px solid rgba(0,0,0,0.1);\n border-radius: 50%;\n border-top-color: #1d9bf0;\n animation: spin 1s linear infinite;\n margin: 0 auto;\n}\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n.reply-sort {\n display: flex;\n gap: 10px;\n align-items: center;\n}\n.close-btn {\n cursor: pointer;\n font-size: 16px;\n}\n.like_counts{\ncolor:#999;\nfont-size:10px;\nmargin-left:auto;\npadding-right:8px\n}\n .float-btn {\n width: 25px;\n height: 25px;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.5);\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n transition: all 0.3s ease;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n -webkit-tap-highlight-color: transparent !important;\n tap-highlight-color: transparent !importan;\n outline: none !important;\n -webkit-tap-highlight-color: transparent !important;\n }\n \n.float-btn:focus,\n.float-btn:focus-visible,\n.float-btn:active,\n.float-btn:-moz-focusring {\n outline: none !important;\n box-shadow: none !important;\n}\n.morerep{\ntext-align:right;\ncolor:#4590B5;\nfont-size:11px\n}\n .float-btn:hover {\n background: rgba(0, 0, 0, 0.7);\n transform: scale(1.1);\n }\n .error-message{\n \tbackground:#eee;\n padding:15px;\n font-size:14px;\n \t}\n\n .media-preview::before {\n content: \"⬇️ \";\n }\n .comment-media[open] summary .media-preview::before {\n content: \"⬆️ \";\n }\n .url-icon img { vertical-align: middle; margin: 0 1px;width:1em; height:1em}\n .surl-text { color: #1E88E5; margin-right: 5px; }\n @media (max-width: 500px) {\n .image-gallery { grid-template-columns: repeat(3, 1fr); }\n body { padding: 10px; }\n .main-content, .comments-section { padding: 12px; }\n } \n \n\n .viewer-open {\n overflow: hidden;\n \/* position: fixed;*\/\n width: 100%;\n }\n \n \n .star-modal {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.7);\n z-index: 2000;\n justify-content: center;\n align-items: center;\n animation: fadeIn 0.3s;\n }\n \n .star-modal-content {\n background: white;\n border-radius: 12px;\n width: 90%;\n max-width: 500px;\n max-height: 60vh;\n overflow-y: auto;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);\n position: relative;\n animation: slideUp 0.3s;\n }\n \n .star-close-btn {\n position: absolute;\n top: 15px;\n right: 20px;\n font-size: 22px;\n font-weight: bold;\n color: #666;\n cursor: pointer;\n z-index: 10;\n transition: color 0.3s;\n }\n \n .star-close-btn:hover {\n color: #ff4757;\n }\n \n .sart-modal-body {\n padding: 20px;\n }\n \n @keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes slideUp {\n from { \n opacity: 0;\n transform: translateY(50px);\n }\n to { \n opacity: 1;\n transform: translateY(0);\n }\n }\n \n #ai-body{\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"PingFang SC\", \"Microsoft YaHei\", sans-serif;\n line-height: 1.6;\n color: #333;\n background-color: #f8fafc;\n margin: 0;\n padding: 20px;\n max-width: 800px;\n margin: 0 auto;\n \n \n }\n\n\n \n \n .ai-h3 {\n color: #1565c0; \n font-size: 1em;\n font-weight: 600;\n margin: 25px 0 15px 0;\n padding-bottom: 8px;\n border-bottom: 2px solid #bbdefb;\n }\n\n \n .ai-content {\n font-size: 0.8em;\n margin: 15px 0;\n color: #374151;\n }\n\n \n .ai-listp {\n font-weight: 600;\n margin: 20px 0 10px 0;\n color: #1e88e5; \n font-size: 0.8em;\n }\n\n \n .ai-list {\n margin: 8px 0;\n padding-left: 25px; \n color: #4b5563;\n list-style: none;\n position: relative;\n text-indent: 0; \n }\n\n .ai-list::before {\n content: \"\";\n position: absolute;\n left: 10px; \n top: 0.7em;\n width: 6px;\n height: 6px;\n background-color: #1e88e5; \n border-radius: 50%;\n }\n\n \n .data-table {\n width: auto; \n border-collapse: collapse;\n margin: 20px 0;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n background: white;\n border-radius: 8px;\n overflow: hidden;\n min-width: 100%; \n }\n\n \n .ai-thead {\n background: linear-gradient(135deg, #1565c0, #1e88e5);\n }\n\n .ai-th {\n padding: 15px 12px;\n text-align: center; \n font-weight: 600;\n color: white;\n border-bottom: 2px solid #64b5f6;\n white-space: nowrap; \n }\n\n \n .ai-tbody-tr {\n border-bottom: 1px solid #f1f5f9;\n transition: background-color 0.2s;\n }\n\n .ai-tbody-tr:hover {\n background-color: #e3f2fd;\n }\n\n .ai-tbody-td {\n padding: 12px;\n border-bottom: 1px solid #f8fafc;\n text-align: left; \n }\n.media-block {\n width: 100%;\n height: 180px;\n background: #f8fafc;\n overflow-x: auto;\n overflow-y: hidden; \n}\n\n.media-c {\n width: auto; \n display: flex;\n flex-wrap: nowrap; \n gap: 10px;\n justify-content: flex-start;\n margin: 15px 0;\n height: 100%;\n}\n\n.media-block div[data-type] {\n flex: 0 0 calc(33.333% - 7px);\n min-width: 0;\n box-sizing: border-box;\n height: 150px;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n min-width: 120px;\n position: relative; \n}\n\n\n.media-block div[data-type=\"v\"]::after {\n content: \"视频\"; \n position: absolute;\n bottom: 8px;\n left: 8px;\n background: rgba(0, 0, 0, 0.7); \n color: white;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 10px;\n z-index: 2; \n}\n\n.media-block div[data-type=\"p\"]::after {\n content: \"图片\";\n position: absolute;\n bottom: 8px;\n left: 8px;\n background: rgba(0, 0, 0, 0.7); \n color: white;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 10px;\n z-index: 2;\n}\n\n.media-block img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 6px;\n position: relative;\n z-index: 1;\n}\n\n\n \n .ai-h3 {\n font-size: 1em;\n }\n \n .ai-th, .ai-tbody-td {\n padding: 10px 8px;\n font-size: 0.6em;\n }\n \n .data-table {\n display: block;\n overflow-x: auto;\n width: 100%; \n }\n \n .ai-th {\n white-space: normal;\n }\n }\n\n \n strong {\n color: #1565c0; \n font-weight: 600;\n }\n\n ",
"type": 0
}