// ==UserScript== // @name B站一键备注 Rev // @namespace https://github.com/kaixinol/ // @version 2.6.1 // @author Kaesinol // @description B站UP主一键备注 | B站一键备注 Rev 的重写版本 // @license AGPL-3.0-or-later // @icon https://www.bilibili.com/favicon.ico // @website https://github.com/kaixinol/Bilibili-User-Memo // @supportURL https://github.com/kaixinol/Bilibili-User-Memo/issues // @match https://*.bilibili.com/* // @exclude https://*.hdslb.com/* // @require https://cdn.jsdelivr.net/npm/alpinejs@3.15.12/dist/cdn.min.js // @require https://cdn.jsdelivr.net/npm/opencc-js@1.3.0/dist/umd/full.js // @require https://cdn.jsdelivr.net/npm/query-selector-shadow-dom@1.0.1/dist/querySelectorShadowDom.js // @connect api.bilibili.com // @grant GM.xmlHttpRequest // @grant GM_addStyle // @grant GM_addValueChangeListener // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_setValue // @grant unsafeWindow // @run-at document-body // @contributionAmount 10¥ // @contributionURL https://s2.loli.net/2025/08/04/1hjKA5qwXHS8Glu.webp // @noframes // @downloadURL https://update.greasyfork.icu/scripts/565831/B%E7%AB%99%E4%B8%80%E9%94%AE%E5%A4%87%E6%B3%A8%20Rev.user.js // @updateURL https://update.greasyfork.icu/scripts/565831/B%E7%AB%99%E4%B8%80%E9%94%AE%E5%A4%87%E6%B3%A8%20Rev.meta.js // ==/UserScript== (function (Alpine, querySelectorShadowDom, openccJs) { 'use strict'; const d=new Set;const importCSS = async e=>{d.has(e)||(d.add(e),(t=>{typeof GM_addStyle=="function"?GM_addStyle(t):(document.head||document.documentElement).appendChild(document.createElement("style")).append(t);})(e));}; function storageHas(key,storage){return null!==storage.getItem(key)}function storageGet(key,storage){let value=storage.getItem(key);if(void 0!==value)return JSON.parse(value)}function storageSet(key,value,storage){storage.setItem(key,JSON.stringify(value));}function getGmValue(key,fallback){return _GM_getValue(key,fallback)}function setGmValue(key,value){_GM_setValue(key,value);}function showAlert(message){window.alert(message);}function confirmDialog(message){return window.confirm(message)}function querySelectorDeep(selector){return querySelectorShadowDom.querySelectorDeep(selector)}function querySelectorAllDeep(selector,root){return querySelectorShadowDom.querySelectorAllDeep(selector,root)}function normalizeUid(value){if(null==value)return null;const uid=String(value).trim();return uid.length>0?uid:null}function getAttr(el,name){return normalizeUid(el.getAttribute(name))}function getAttrFromQuery(root,selector,attribute){const target=root.querySelector(selector);return target?normalizeUid(target.getAttribute(attribute)):null}function parseUidFromDataId(value){return value?normalizeUid(value.split("_")[1]):null}function readPreferredText(node){if(!node)return null;const original=node.dataset.biliOriginal?.trim();if(original)return original;const text=node.textContent?.trim();return text||null}function resolveRuleTextTarget(el,rule){return rule.textSelector?isDynamicMode(rule)?function(rule){return "trigger"in rule}(rule)?function(el,rule,textSelector){if(el.matches(textSelector))return el;const childTextEl=el.querySelector(textSelector);if(childTextEl)return childTextEl;const directContainer=el.closest(rule.trigger.watch);if(directContainer)return directContainer.querySelector(textSelector);const watchTargets=querySelectorAllDeep(rule.trigger.watch);for(const target of watchTargets){const scope=target.shadowRoot||target;if(scope.contains(el))return scope.querySelector(textSelector)}const first=watchTargets[0];return first?(first.shadowRoot||first).querySelector(textSelector):null}(el,rule,rule.textSelector):null:function(el,textSelector){return el.querySelector(textSelector)||(el.matches(textSelector)?el:null)}(el,rule.textSelector):el}function syncRenderedNodeState(el,user,originalName,displayMode,options={}){const text=function(user,fallbackName,displayMode){const nickname=(user?.nickname||fallbackName||"").trim(),memo=(user?.memo||"").trim();if(!memo)return nickname;switch(displayMode){case 0:default:return nickname;case 1:return `${memo}(${nickname})`;case 2:return `${nickname}(${memo})`;case 3:return memo}}(user,originalName,displayMode);el.textContent!==text&&(el.textContent=text);const shouldHighlight=Boolean(!options.isEditableWrapper&&user?.memo&&user.memo!==originalName&&text!==originalName);el.classList.toggle("bili-memo-tag",shouldHighlight);}function syncElementMeta(el,meta){el.dataset.biliUid!==meta.uid&&(el.dataset.biliUid=meta.uid);el.dataset.biliOriginal!==meta.originalName&&(el.dataset.biliOriginal=meta.originalName);}function refreshTag(tag,user,displayMode){const originalName=tag.getAttribute("data-bili-original")||"";syncRenderedNodeState(tag,user,originalName,displayMode,{isEditableWrapper:tag.classList.contains("editable-textarea")});}function getUserAvatarFromDOM(userID){logger_debug(`Getting avatar for user ${userID}, called from: ${function(depth=3){const frame=(new Error).stack?.split("\n")?.[depth]?.trim();if(!frame)return "unknown";const nameMatch=frame.match(/at\s+(?:async\s+)?([^(]+)/),funcName=nameMatch?nameMatch[1].trim():"?",pathMatch=frame.match(/\(([^)]+)\)/),modulePart=(pathMatch?pathMatch[1]:"").replace(/^https?:\/\/[^/]+/,"").replace(/\?.*$/,"").replace(/:\d+(:\d+)?$/,"").replace(/^\/?src\//,"").replace(/\.[a-z0-9]+$/,"").replace(/\//g,".");return modulePart?`${modulePart}:${funcName}`:funcName}()}`);const rules=[{selector:`#user-avatar[data-user-profile-id="${userID}"] bili-avatar source`,attr:"srcset"},{selector:`#user-avatar[data-user-profile-id="${userID}"] img`,attr:"src"},{selector:`a[href*="${userID}"] img.bili-avatar-img`,attr:"data-src"},{selector:".bili-dyn-item__main source",attr:"srcset"},{selector:"div.avatar source",attr:"srcset"}];for(const{selector:selector,attr:attr}of rules){const el=querySelectorDeep(selector);logger_debug();const val=el?.getAttribute(attr);if(val)return val}return DEFAULT_AVATAR_URL}function normalizeUserCollection(raw,options){const users=new Map;(function(raw){return Array.isArray(raw)?raw:raw&&"object"==typeof raw?Object.values(raw):[]})(raw).forEach(entry=>{const normalized=function(raw,{requireMemo:requireMemo=false,requireNickname:requireNickname=false,fallbackNicknameToId:fallbackNicknameToId=false}={}){if(!raw||"object"!=typeof raw)return null;const record2=raw,id=String(record2.id??record2.bid??"").trim();if(!id)return null;const memo=String(record2.memo??"").trim();if(requireMemo&&!memo)return null;let nickname=String(record2.nickname??"").trim();!nickname&&fallbackNicknameToId&&(nickname=id);return requireNickname&&!nickname?null:{id:id,nickname:nickname,avatar:String(record2.avatar||DEFAULT_AVATAR_URL),memo:memo,isDeleted:true===record2.isDeleted||void 0}}(entry,options);normalized&&users.set(normalized.id,normalized);});return Array.from(users.values())}function normalizeDisplayMode(value){return "number"==typeof value&&value>=0&&value<=3?value:2}function normalizeUsers(raw){return normalizeUserCollection(raw,{requireMemo:true,fallbackNicknameToId:true})}function saveUsersToStorage(users){setGmValue("biliUsers",users);}function usersEqual(a,b){if(a.length!==b.length)return false;for(let i=0;i!isOwnedNode(mutation.target)&&Array.from(mutation.addedNodes).some(node=>!isOwnedNode(node)))}function hasExternalRemovedNodes(mutations){return mutations.some(mutation=>!isOwnedNode(mutation.target)&&Array.from(mutation.removedNodes).some(node=>!isOwnedNode(node)))}function ensureMemoStyleSheets(root){const sheets=root.adoptedStyleSheets,hasGlobal=sheets.includes(GLOBAL_STYLE_SHEET),hasCustom=!CUSTOM_MEMO_STYLE_SHEET||sheets.includes(CUSTOM_MEMO_STYLE_SHEET);if(hasGlobal&&hasCustom)return;const next=sheets.slice();hasGlobal||next.push(GLOBAL_STYLE_SHEET);!hasCustom&&CUSTOM_MEMO_STYLE_SHEET&&next.push(CUSTOM_MEMO_STYLE_SHEET);root.adoptedStyleSheets=next;}function ensureStylesForElement(target){const root=target.getRootNode();(root instanceof ShadowRoot||root instanceof Document)&&ensureMemoStyleSheets(root);}function resolveWatchScope(target){return target.shadowRoot||target}function isNodeInsideScope(node,scope){if(scope===document)return node.isConnected;let current=node;for(;current;){if(current===scope)return true;current=current instanceof ShadowRoot?current.host:current.parentNode;}return false}function getWatchTarget(selector){return querySelectorDeep(selector)}function shouldHandleDiscoveryMutations(mutations){return {hasAddedNodes:hasExternalAddedNodes(mutations),hasRemovedNodes:hasExternalRemovedNodes(mutations)}}function delay(ms){return new Promise(resolve=>{window.setTimeout(resolve,ms);})}function nextFrame(){return new Promise(resolve=>{window.requestAnimationFrame(()=>resolve());})}function requestIdle(callback,timeout=1e3){const requestIdleCallback=window.requestIdleCallback;requestIdleCallback?requestIdleCallback(callback,{timeout:timeout}):window.setTimeout(()=>callback({timeRemaining:()=>16}),16);}function applyCustomFontColor(color){color?document.documentElement.style.setProperty("--custom-font-color",color):document.documentElement.style.removeProperty("--custom-font-color");}function applyTheme(dark){document.documentElement.classList.toggle("memo-container-dark-theme",dark);}function persistWithGmStorage(key,initialValue){const persistFactory=Alpine.$persist;return persistFactory?persistFactory(initialValue).as(key).using(gmPersistStorage):initialValue}function createPanelPrefsStore({getUserListStore:getUserListStore2}){const initialOpenText=getGmValue("btn_open_text","UvU"),initialCloseText=getGmValue("btn_close_text","UwU"),initialDarkTheme=getGmValue("isDark",false),initialFontColor=getGmValue("customFontColor","").trim(),initialMemoCss=getGmValue("customMemoCss","");return {initialized:false,openText:persistWithGmStorage("toggle.openText",initialOpenText),closeText:persistWithGmStorage("toggle.closeText",initialCloseText),isDark:persistWithGmStorage("theme.isDark",initialDarkTheme),customFontColor:persistWithGmStorage("style.customFontColor",initialFontColor),customMemoCss:persistWithGmStorage("style.customMemoCss",initialMemoCss),cssStatus:"",showAdvancedCss:false,init(){if(this.initialized)return;this.initialized=true;applyTheme(this.isDark);getUserListStore2().isDark=this.isDark;const cssVarColor=document.documentElement.style.getPropertyValue("--custom-font-color").trim();this.customFontColor=this.customFontColor||cssVarColor;applyCustomFontColor(this.customFontColor);this.applyMemoCss();},toggleTheme(){this.isDark=!this.isDark;getUserListStore2().isDark=this.isDark;applyTheme(this.isDark);},editToggleText(isOpen){const nextText=function(message,defaultValue=""){const result=window.prompt(message,defaultValue);return null===result?null:result.trim()||null}("修改文字:",isOpen?this.openText:this.closeText);nextText&&(isOpen?this.openText=nextText:this.closeText=nextText);},onCustomColorInput(){applyCustomFontColor(this.customFontColor);},clearCustomColor(){this.customFontColor="";applyCustomFontColor("");showAlert("已取消自定义字体颜色");},closeAdvancedCss(){this.showAdvancedCss=false;},applyMemoCss(){const nextCss=this.customMemoCss||"",result=function(css){const nextCss=css??"";if(!nextCss.trim()&&!CUSTOM_MEMO_STYLE_SHEET)return {ok:true,ruleCount:0};try{CUSTOM_MEMO_STYLE_SHEET||(CUSTOM_MEMO_STYLE_SHEET=new CSSStyleSheet);CUSTOM_MEMO_STYLE_SHEET.replaceSync(nextCss);}catch(error){const message=error instanceof Error?error.message:`未知错误: ${String(error)}`;logger_warn("⚠️ 自定义备注 CSS 解析失败:",error);return {ok:false,error:message,ruleCount:CUSTOM_MEMO_STYLE_SHEET?.cssRules.length??0}}!function(){const targets=querySelectorAllDeep(".bili-memo-tag, .editable-textarea, .bili-memo-input");if(!targets||0===targets.length)return;const roots=new Set;targets.forEach(el=>{const root=el.getRootNode();(root instanceof ShadowRoot||root instanceof Document)&&roots.add(root);});roots.forEach(root=>ensureMemoStyleSheets(root));}();return {ok:true,ruleCount:CUSTOM_MEMO_STYLE_SHEET.cssRules.length}}(nextCss);this.cssStatus=function(css,result){const lintResult=function(css){const trimmedCss=css.trim();if(!trimmedCss)return null;let quote=null,escaped=false,commentDepth=0,braces=0,parentheses=0,brackets=0;for(let index=0;index0){if("*"===current&&"/"===next){commentDepth-=1;index+=1;}}else if(quote){if(escaped){escaped=false;continue}if("\\"===current){escaped=true;continue}current===quote&&(quote=null);}else if("/"!==current||"*"!==next)if("'"!==current&&'"'!==current){"{"===current?braces+=1:"}"===current?braces-=1:"("===current?parentheses+=1:")"===current?parentheses-=1:"["===current?brackets+=1:"]"===current&&(brackets-=1);if(braces<0)return "多余的 '}'";if(parentheses<0)return "多余的 ')'";if(brackets<0)return "多余的 ']'"}else quote=current;else {commentDepth+=1;index+=1;}}return commentDepth>0?"注释未闭合":quote?`字符串未闭合:${quote}`:braces>0?"缺少 '}'":parentheses>0?"缺少 ')'":brackets>0?"缺少 ']'":null}(css);if(lintResult)return `CSS 语法警告:${lintResult}`;if(!result.ok)return `CSS 语法错误:${result.error||"无法解析"}`;const parsingWarning=function(css,ruleCount){if(!css.trim())return null;if(0!==(ruleCount||0))return null;const strippedCss=css.replace(/\/\*[\s\S]*?\*\//g,"").replace(/"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/g,"");return /{/.test(strippedCss)?"浏览器未解析出任何规则,可能语法错误被忽略":null}(css,result.ruleCount);return parsingWarning?`CSS 解析警告:${parsingWarning}`:""}(nextCss,result);}}} // @__NO_SIDE_EFFECTS__ function getGlobalConfig(config$1){return {lang:config$1?.lang??void 0,message:config$1?.message,abortEarly:config$1?.abortEarly??void 0,abortPipeEarly:config$1?.abortPipeEarly??void 0}} // @__NO_SIDE_EFFECTS__ function _stringify(input){const type=typeof input;return "string"===type?`"${input}"`:"number"===type||"bigint"===type||"boolean"===type?`${input}`:"object"===type||"function"===type?(input&&Object.getPrototypeOf(input)?.constructor?.name)??"null":type}function _addIssue(context,label,dataset,config$1,other){const input=other&&"input"in other?other.input:dataset.value,expected=other?.expected??context.expects??null,received=other?.received??_stringify(input),issue={kind:context.kind,type:context.type,input:input,expected:expected,received:received,message:`Invalid ${label}: ${expected?`Expected ${expected} but r`:"R"}eceived ${received}`,requirement:context.requirement,path:other?.path,issues:other?.issues,lang:config$1.lang,abortEarly:config$1.abortEarly,abortPipeEarly:config$1.abortPipeEarly},isSchema="schema"===context.kind,message$1=other?.message??context.message??(context.reference,void issue.lang)??(isSchema?void issue.lang:null)??config$1.message??void issue.lang;void 0!==message$1&&(issue.message="function"==typeof message$1?message$1(issue):message$1);isSchema&&(dataset.typed=false);dataset.issues?dataset.issues.push(issue):dataset.issues=[issue];} // @__NO_SIDE_EFFECTS__ function _getStandardProps(context){return {version:1,vendor:"valibot",validate:value$1=>context["~run"]({value:value$1},getGlobalConfig())}} // @__NO_SIDE_EFFECTS__ function _isValidObjectKey(object$1,key){return Object.hasOwn(object$1,key)&&"__proto__"!==key&&"prototype"!==key&&"constructor"!==key} // @__NO_SIDE_EFFECTS__ function _joinExpects(values$1,separator){const list=[...new Set(values$1)];return list.length>1?`(${list.join(` ${separator} `)})`:list[0]??"never"} // @__NO_SIDE_EFFECTS__ function getFallback(schema,dataset,config$1){return "function"==typeof schema.fallback?schema.fallback(dataset,config$1):schema.fallback} // @__NO_SIDE_EFFECTS__ function getDefault(schema,dataset,config$1){return "function"==typeof schema.default?schema.default(dataset,config$1):schema.default} // @__NO_SIDE_EFFECTS__ function array(item,message$1){return {kind:"schema",type:"array",reference:array,expects:"Array",async:false,item:item,message:message$1,get"~standard"(){ return _getStandardProps(this)},"~run"(dataset,config$1){const input=dataset.value;if(Array.isArray(input)){dataset.typed=true;dataset.value=[];for(let key=0;keyoption.expects),"|"),async:false,options:options,message:message$1,get"~standard"(){ return _getStandardProps(this)},"~run"(dataset,config$1){let validDataset,typedDatasets,untypedDatasets;for(const schema of this.options){const optionDataset=schema["~run"]({value:dataset.value},config$1);if(optionDataset.typed){if(!optionDataset.issues){validDataset=optionDataset;break}typedDatasets?typedDatasets.push(optionDataset):typedDatasets=[optionDataset];}else untypedDatasets?untypedDatasets.push(optionDataset):untypedDatasets=[optionDataset];}if(validDataset)return validDataset;if(typedDatasets){if(1===typedDatasets.length)return typedDatasets[0];_addIssue(this,"type",dataset,config$1,{issues:_subIssues(typedDatasets)});dataset.typed=true;}else {if(1===untypedDatasets?.length)return untypedDatasets[0];_addIssue(this,"type",dataset,config$1,{issues:_subIssues(untypedDatasets)});}return dataset}}} // @__NO_SIDE_EFFECTS__ function safeParse(schema,input,config$1){const dataset=schema["~run"]({value:input},getGlobalConfig(config$1));return {typed:dataset.typed,success:!dataset.issues,output:dataset.value,issues:dataset.issues}}function formatIssues(issues){return issues.slice(0,2).map(({path:path,message:message})=>{const pathStr=path?.map(p=>p.key).filter(Boolean).join(".")||"";return pathStr?`[${pathStr}] ${message}`:message}).join("; ")}function decode(body){const form=new FormData;body.trim().split("&").forEach(function(bytes){if(bytes){const split=bytes.split("="),name=split.shift()?.replace(/\+/g," "),value=split.join("=").replace(/\+/g," ");form.append(decodeURIComponent(name),decodeURIComponent(value));}});return form}async function GM_fetch(input,init){const request=new Request(input,init);let data;init?.body&&(data=await request.text());return await function(request,init,data){return new Promise((resolve,reject)=>{if(request.signal&&request.signal.aborted)return reject(new DOMException("Aborted","AbortError"));GM.xmlHttpRequest({url:request.url,method:gmXHRMethod(request.method.toUpperCase()),headers:Object.fromEntries(new Headers(init?.headers).entries()),data:data,responseType:"blob",onload(res){try{resolve(function(req,res){const headers=function(h){const s=h.trim();if(!s)return new Headers;const array2=s.split("\r\n").map(value=>{let s2=value.split(":");return [s2[0].trim(),s2[1].trim()]});return new Headers(array2)}(res.responseHeaders),body="string"==typeof res.response?new Blob([res.response],{type:headers.get("Content-Type")||"text/plain"}):res.response;return new ResImpl(body,{statusCode:res.status,statusText:res.statusText,headers:headers,finalUrl:res.finalUrl,redirected:res.finalUrl===req.url})}(request,res));}catch(e){reject(e);}},onabort(){reject(new DOMException("Aborted","AbortError"));},ontimeout(){reject(new TypeError("Network request failed, timeout"));},onerror(err){reject(new TypeError("Failed to fetch: "+err.finalUrl));}});})}(request,init,data)}function gmXHRMethod(method){if(function(array2,element){return httpMethods.includes(element)}(0,method))return method;throw new Error(`unsupported http method ${method}`)}function validateConcurrency(concurrency){if(!Number.isInteger(concurrency)&&concurrency!==Number.POSITIVE_INFINITY||!(concurrency>0))throw new TypeError("Expected `concurrency` to be a number from 1 and up")}function createConverter(from,to){const cacheKey=`${from}->${to}`,cached=converterCache.get(cacheKey);if(void 0!==cached)return cached;try{const converter=openccJs.Converter({from:from,to:to});converterCache.set(cacheKey,converter);return converter}catch(error){console.warn(`[Bilibili-User-Memo] 简繁搜索转换器初始化失败 (${from} -> ${to})`,error);converterCache.set(cacheKey,null);return null}}function convertWith(converter,text){if(!converter||!text)return text;try{return converter(text)}catch{return text}}function getSearchForms(value){const raw=value.trim().toLowerCase(),cached=searchFormCache.get(raw);if(cached)return cached;const toSimplified=createConverter("tw","cn"),toTraditional=createConverter("cn","tw"),variants=Array.from(new Set([raw,convertWith(toSimplified,raw),convertWith(toTraditional,raw)].filter(Boolean))),forms={raw:raw,variants:variants};searchFormCache.set(raw,forms);return forms}function matchesChineseSearch(value,queryForms,enableFuzzySearch=false){if(!queryForms.raw)return true;const targetForms=getSearchForms(String(value||""));return enableFuzzySearch?queryForms.variants.some(query=>targetForms.variants.some(target=>function(query,target){return query&&target?!!(target.includes(query)||isSubsequence(query,target)||query.length>target.length&&isSubsequence(target,query)||function(query,target){if(query.length>target.length)return false;const targetChars=new Set(target);for(const ch of query)if(!targetChars.has(ch))return false;return true}(query,target)):!query}(query,target))):queryForms.variants.some(query=>targetForms.variants.some(target=>target.includes(query)))}function isSubsequence(query,target){let qi=0;for(let ti=0;tiuser.id));for(const id of Array.from(store._usersMap.keys()))nextIds.has(id)||store._usersMap.delete(id);const nextList=[];users.forEach(user=>{const existing=store._usersMap.get(user.id);if(existing){existing.nickname=user.nickname;existing.avatar=user.avatar;existing.memo=user.memo;nextList.push(existing);return}const reactiveUser=Alpine.reactive({...user});store._usersMap.set(reactiveUser.id,reactiveUser);nextList.push(reactiveUser);});store._usersList.splice(0,store._usersList.length,...nextList);0!==store.selectedIds.length&&(store.selectedIds=store.selectedIds.filter(id=>nextIds.has(id)));}(this,users);},resetUsersSnapshot(){this._usersMap.clear();this._usersList.length=0;},removeUser(userId){userStore.removeUser(userId);},isDark:getGmValue("isDark",false),fuzzySearchEnabled:getGmValue("panelFuzzySearch",false),preloadAllCards:preloadAllCards,isUsersLoading:false,hasLoadedUsers:shouldPreloadImmediately,isRefreshing:false,refreshCurrent:0,refreshTotal:0,displayMode:userStore.displayMode,searchQuery:"",isMultiSelect:false,selectedIds:[],get filteredUsers(){const query=this.searchQuery.trim();if(!query)return this._usersList;const queryForms=getSearchForms(query);return queryForms.raw?this._usersList.filter(user=>String(user.id||"").includes(query)||matchesChineseSearch(user.nickname,queryForms,this.fuzzySearchEnabled)||matchesChineseSearch(user.memo,queryForms,this.fuzzySearchEnabled)):this._usersList},updateUser(id,updates){const before=this.getUserById(id);before&&userStore.updateUser(id,updates,before.nickname||id);},toggleMultiSelect(){this.isMultiSelect=!this.isMultiSelect;this.isMultiSelect||this.clearSelection();},clearSelection(){this.selectedIds=[];},invertSelection(ids){if(0===ids.length)return;const current=new Set(this.selectedIds),next=new Set(current);ids.forEach(id=>{next.has(id)?next.delete(id):next.add(id);});this.selectedIds=Array.from(next);},removeSelected(){if(0!==this.selectedIds.length){userStore.removeUsers(this.selectedIds);this.clearSelection();}},setDisplayMode(mode){userStore.setDisplayMode(mode);},setFuzzySearchEnabled(next){const shouldEnable=Boolean(next);if(shouldEnable!==this.fuzzySearchEnabled){this.fuzzySearchEnabled=shouldEnable;!function(value){setGmValue("panelFuzzySearch",value);}(shouldEnable);}},setOpen(next){const shouldOpen=Boolean(next);this.isOpen=shouldOpen;shouldOpen&&this.ensureUsersLoaded();},setPreloadAllCards(next){const shouldPreload=Boolean(next);this.preloadAllCards=shouldPreload;setPanelPreloadAllCards(shouldPreload);if(shouldPreload){if(this.hasLoadedUsers)return;this.syncUsersSnapshot(userStore.getUsers());this.hasLoadedUsers=true;this.isUsersLoading=false;}else if(!this.isOpen){this.resetUsersSnapshot();this.hasLoadedUsers=false;this.isUsersLoading=false;}},async ensureUsersLoaded(){if(this.hasLoadedUsers||this.isUsersLoading)return;this.isUsersLoading=true;await async function(){await async function(frameCount=0,idleTimeout=1e3){await async function(count){for(let index=0;index{const requestIdleCallback=window.requestIdleCallback;requestIdleCallback?requestIdleCallback(()=>resolve(),{timeout:timeout}):window.setTimeout(resolve,0);})}(idleTimeout);}(5,1e3);}();const latestUsers=userStore.getUsers();this.syncUsersSnapshot(latestUsers);this.hasLoadedUsers=true;this.isUsersLoading=false;},async refreshData(){if(!this.isRefreshing&&0!==this._usersList.length){this.isRefreshing=true;this.refreshCurrent=0;this.refreshTotal=this._usersList.length;try{const profiles=await async function(users,onProgress){const profiles=[],tasks=users.map(async user=>{try{const newData=await getUserInfo(String(user.id));if(!newData.nickname)return;profiles.push({id:user.id,nickname:newData.nickname,avatar:newData.avatar,isDeleted:newData.isDeleted});}catch(error){logger_error(`刷新用户 [${user.id}] 失败:`,error);}finally{onProgress();}});await Promise.allSettled(tasks);return profiles}(this.users,()=>{this.refreshCurrent++;});userStore.updateUserProfiles(profiles);}finally{await delay(1e3);this.isRefreshing=false;}}},exportData(){!function(users){const exportData=users.map(user=>{const data={id:user.id,nickname:user.nickname,memo:user.memo||""};user.avatar&&user.avatar!==DEFAULT_AVATAR_URL&&(data.avatar=user.avatar);true===user.isDeleted&&(data.isDeleted=true);return data}),jsonContent=JSON.stringify(exportData,null,2),blob=new Blob([jsonContent],{type:"application/json"}),url=URL.createObjectURL(blob),a=document.createElement("a");a.href=url;a.download=`bili-user-notes-${(new Date).toISOString().split("T")[0]}.json`;a.click();URL.revokeObjectURL(url);}(this.users);showAlert(`导出成功!\n已导出 ${this._usersList.length} 个用户的数据`);},async importData(){const readResult=await async function(){const file=await new Promise(resolve=>{const input=document.createElement("input");let settled=false;const finish=file=>{if(!settled){settled=true;resolve(file);}};input.type="file";input.accept="application/json";input.onchange=()=>{finish(input.files?.[0]||null);};input.oncancel=()=>finish(null);input.click();});if(!file)return {status:"cancelled"};try{const parsedData=JSON.parse(await file.text()),validation=function(data){const result=safeParse(CombinedSchema,data);return result.success?{ok:!0}:{ok:!1,error:`格式不匹配: ${formatIssues(result.issues)}`}}(parsedData);if(!validation.ok)return {status:"error",message:`导入失败:${validation.error}`};const importedUsers=normalizeUserCollection(parsedData,{requireNickname:!0});return 0===importedUsers.length?{status:"error",message:"导入失败:没有有效的用户数据"}:{status:"ok",users:importedUsers}}catch{return {status:"error",message:"导入失败:JSON 格式错误或数据解析失败"}}}();if("cancelled"===readResult.status)return;if("error"===readResult.status){showAlert(readResult.message);return}const result=userStore.upsertImportedUsers(readResult.users);0!==result.added||0!==result.updated?showAlert(`导入成功!\n新增:${result.added} 个用户\n更新:${result.updated} 个用户`):showAlert("导入完成,但没有可应用的变更");}};Alpine.store("userList",store);const reactiveStore=Alpine.store("userList");shouldPreloadImmediately&&reactiveStore.syncUsersSnapshot(userStore.getUsers());const syncUsers=users=>{reactiveStore.hasLoadedUsers&&reactiveStore.syncUsersSnapshot(users);};userStore.subscribe(change=>{if("displayMode"!==change.type)if("users"!==change.type){syncUsers(change.users);reactiveStore.displayMode=change.displayMode;}else syncUsers(change.users);else reactiveStore.displayMode=change.displayMode;});}function getUserListStore(){return Alpine.store("userList")}function getPanelPrefsStore(){return Alpine.store("panelPrefs")}function runOnNextTick(context,callback){context.$nextTick?.(callback);}function getRef(context,key){return context.$refs?.[key]}function getCurrentElement(context){return context.$el}function useUserListStore(){return Alpine.store("userList")}function loadDisabledPageScopes(){const raw=getGmValue("disabledPageScopes",[]);if(!Array.isArray(raw))return [];const seen=new Set,patterns=[];raw.forEach(entry=>{if("string"!=typeof entry)return;const pattern=entry.trim();if(pattern&&!seen.has(pattern)){seen.add(pattern);patterns.push(pattern);}});return patterns}function saveDisabledPageScopes(patterns){setGmValue("disabledPageScopes",patterns);}var module_default=function(Alpine2){let persist=()=>{let alias,storage;try{storage=localStorage;}catch(e){console.error(e);console.warn("Alpine: $persist is using temporary storage since localStorage is unavailable.");let dummy=new Map;storage={getItem:dummy.get.bind(dummy),setItem:dummy.set.bind(dummy)};}return Alpine2.interceptor((initialValue,getter,setter,path,key)=>{let lookup=alias||`_x_${path}`,initial=storageHas(lookup,storage)?storageGet(lookup,storage):initialValue;setter(initial);Alpine2.effect(()=>{let value=getter();storageSet(lookup,value,storage);setter(value);});return initial},func=>{func.as=key=>{alias=key;return func},func.using=target=>{storage=target;return func};})};Object.defineProperty(Alpine2,"$persist",{get:()=>persist()});Alpine2.magic("persist",persist);Alpine2.persist=(key,{get:get,set:set},storage=localStorage)=>{let initial=storageHas(key,storage)?storageGet(key,storage):get();set(initial);Alpine2.effect(()=>{let value=get();storageSet(key,value,storage);set(value);});};};importCSS(".panel-container{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;z-index:9999;background:var(--bg-main);border-top:2px solid var(--primary-color);height:46vh;transition:transform .3s cubic-bezier(.4,0,.2,1);position:fixed;bottom:0;left:0;right:0;box-shadow:0 -4px 12px #00000014}.panel-container.closed{transform:translateY(100%)}.panel-container.open{transform:translateY(0%)}.panel-inner{box-sizing:border-box;flex-direction:column;height:100%;padding:12px 20px;display:flex;position:relative}.panel-toggle-btn{cursor:context-menu;width:70px;height:34px;color:var(--text-inverse);background:var(--primary-color);-webkit-user-select:none;user-select:none;border:none;border-radius:8px 8px 0 0;justify-content:center;align-items:center;font-size:18px;transition:opacity .3s,background .2s,top .2s;display:flex;position:absolute;top:-34px;left:20px}.panel-toggle-btn:hover{background:var(--primary-color);opacity:1!important}.panel-mode-section{align-items:center;gap:18px;padding:8px 12px;font-size:16px;display:flex;position:relative}.panel-right-actions{align-items:center;gap:10px;margin-left:auto;display:flex}.panel-custom-css-section{background:var(--bg-sub);border:1px solid var(--border-main);border-radius:10px;flex-direction:column;gap:6px;margin-top:8px;padding:8px 12px;display:flex}.panel-custom-css-title{color:var(--text-main);font-size:13px;font-weight:600}.panel-custom-css-input{resize:vertical;border:1px solid var(--border-main);background:var(--bg-main);width:100%;min-height:90px;color:var(--text-main);border-radius:8px;outline:none;padding:8px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;transition:border-color .15s,box-shadow .15s}.panel-custom-css-input:focus{border-color:var(--primary-color);box-shadow:0 0 0 2px var(--primary-alpha)}.panel-custom-css-status{color:var(--text-inverse);background:var(--danger-color);border-radius:6px;padding:4px 8px;font-size:12px;line-height:1.4}.panel-custom-css-hint{color:var(--text-sub);font-size:12px;line-height:1.4}.panel-custom-color-setting{background:var(--bg-sub);border:1px solid var(--primary-color);color:var(--text-main);cursor:pointer;border-radius:10px;align-items:center;gap:8px;padding:4px 8px;font-size:13px;display:flex;position:relative}.color-preview{border:1px solid var(--border-main);cursor:pointer;background:var(--custom-font-color,var(--primary-color));border-radius:4px;width:20px;height:20px}.ghost-color-picker{opacity:0;pointer-events:none;border:none;width:0;height:0;margin:0;padding:0;position:absolute;overflow:hidden}.panel-custom-color-setting label{cursor:pointer}.panel-custom-color-setting input[type=color]{border:1px solid var(--border-main);background:var(--bg-main);cursor:pointer;border-radius:6px;width:24px;height:24px;padding:0}.panel-custom-color-setting input[type=color]::-webkit-color-swatch-wrapper{padding:0}.panel-custom-color-setting input[type=color]::-webkit-color-swatch{border:none;border-radius:4px}.panel-theme-toggle{cursor:pointer;color:var(--text-sub);border-radius:8px;justify-content:center;align-items:center;padding:6px;transition:all .2s;display:flex}.panel-theme-toggle:hover{color:var(--primary-color);background:var(--overlay);transform:rotate(20deg)}.memo-container-dark-theme .panel-theme-toggle:hover{background:var(--glass)}[x-cloak]{display:none!important}.panel-theme-toggle svg{stroke-width:2px;width:20px;height:20px}.panel-mode-label{color:var(--text-main);font-size:15px;font-weight:600}.panel-mode-option{color:var(--text-sub);cursor:pointer;align-items:center;gap:6px;font-size:14px;display:flex}.panel-control-bar{align-items:center;gap:12px;padding:12px 0;display:flex}.panel-btn{border:1px solid var(--primary-color);background:var(--bg-main);color:var(--primary-color);cursor:pointer;border-radius:20px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .2s}.panel-btn:hover{background:var(--primary-color);color:var(--text-inverse)}.panel-btn:disabled,.panel-btn.btn-disabled{background-color:var(--border-main);color:var(--text-sub);cursor:not-allowed;opacity:.8;transform:none}.panel-btn.btn-active{background:var(--primary-color);color:var(--text-inverse)}.panel-icon-btn{border:1px solid var(--primary-color);background:var(--bg-main);color:var(--primary-color);cursor:pointer;border-radius:18px;align-items:center;gap:6px;padding:6px 10px;font-size:12px;transition:all .2s;display:inline-flex}.panel-icon-btn svg{width:16px;height:16px}.panel-icon-btn:hover{background:var(--primary-color);color:var(--text-inverse)}.panel-icon-btn:disabled{background-color:var(--border-main);color:var(--text-sub);cursor:not-allowed;opacity:.8;transform:none}.panel-icon-text{font-size:12px}.panel-title{color:var(--text-main);flex-grow:1;font-size:16px;font-weight:700}.panel-search-box{border:1px solid var(--primary-color);background:var(--bg-sub);border-radius:18px;align-items:center;width:180px;padding:6px 10px;transition:all .2s;display:flex}.panel-search-box:focus-within{border-color:var(--primary-color);background:var(--bg-main);box-shadow:0 0 0 2px var(--primary-alpha)}.panel-search-input{width:100%;color:var(--text-main);background:0 0;border:none;outline:none;font-size:14px}.panel-search-clear{color:var(--border-main);cursor:pointer;background:0 0;border:none;padding:0 4px;font-size:14px}.panel-search-clear:hover{color:var(--primary-color)}.panel-fuzzy-search-toggle{color:var(--text-sub);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;align-items:center;gap:4px;font-size:12px;display:inline-flex}.panel-fuzzy-search-toggle input[type=checkbox]{accent-color:var(--primary-color);cursor:pointer;width:14px;height:14px}.panel-fuzzy-search-toggle:hover{color:var(--primary-color)}.memo-container-dark-theme .panel-fuzzy-search-toggle{color:var(--text-sub)}.memo-container-dark-theme .panel-fuzzy-search-toggle:hover{color:var(--primary-color)}.panel-users-container{flex:1;margin-top:10px;padding-right:8px;overflow-y:auto}.panel-users-container::-webkit-scrollbar{width:6px}.panel-users-container::-webkit-scrollbar-thumb{background:var(--border-main);border-radius:10px}.panel-users-container::-webkit-scrollbar-thumb:hover{background:var(--border-main)}.memo-container-dark-theme .panel-container{background:var(--bg-main);border-top-color:var(--primary-color);--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;box-shadow:0 -6px 16px #00000080}.memo-container-dark-theme .panel-toggle-btn{background:var(--primary-color);color:var(--text-inverse)}.memo-container-dark-theme .panel-mode-label{color:var(--text-main)}.memo-container-dark-theme .panel-mode-option{color:var(--text-sub)}.memo-container-dark-theme .panel-btn{color:var(--primary-color);border-color:var(--primary-color);background:0 0}.memo-container-dark-theme .panel-btn:hover{background:var(--primary-color);color:var(--text-main)}.memo-container-dark-theme .panel-icon-btn{color:var(--primary-color);border-color:var(--primary-color);background:0 0}.memo-container-dark-theme .panel-icon-btn:hover{background:var(--primary-color);color:var(--text-main)}.memo-container-dark-theme .panel-search-box{background:var(--bg-sub);border:2px solid var(--primary-color)}.memo-container-dark-theme .panel-search-input{color:var(--text-main)}.memo-container-dark-theme .panel-search-clear{color:var(--text-sub)}.memo-container-dark-theme .panel-users-container::-webkit-scrollbar-thumb{background:var(--border-main)}.memo-container-dark-theme .panel-title{color:var(--text-inverse)}.loading-spinner{animation:2s linear infinite spin;display:inline-block}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}");importCSS("*{box-sizing:border-box}button,input{font-family:inherit}:root{--primary-color:#fb7299;--primary-alpha:#fb729926;--link-color:#00aeec;--bg-main:#fff;--bg-sub:#f6f8fa;--text-main:#333;--text-sub:#666;--text-inverse:#fff;--border-main:#d1d1d1;--shadow-elevated:0 4px 12px #00000026;--shadow-dark:0 8px 24px #0006;--overlay:#00000026;--glass:#ffffff59;--focus-color:#0366d6;--focus-ring:#0366d633;--danger-color:#d73a49;--danger-alpha:#d73a491a;--memo-tag-color:var(--custom-font-color,black);--memo-textarea-color:var(--custom-font-color,black);--memo-textarea-bg:var(--glass);--memo-textarea-border-color:var(--overlay);--memo-input-color:initial}.memo-container-dark-theme{--bg-main:#18181b;--bg-sub:#202024;--border-main:#2f2f33;--text-main:#e5e7eb;--text-sub:#a1a1aa;--link-color:#7dd3fc;--memo-tag-color:var(--custom-font-color,white);--memo-textarea-color:var(--custom-font-color,white);--memo-textarea-bg:var(--overlay);--memo-textarea-border-color:var(--glass);--memo-input-color:var(--text-main)}");importCSS('.panel-users-list{grid-template-columns:repeat(3,1fr);gap:10px;width:100%;display:grid}.panel-empty-state{color:var(--text-sub);grid-column:1/-1;justify-content:center;align-items:center;padding:24px 12px;font-size:14px;display:flex}.panel-loading-state{min-height:120px;color:var(--text-sub);justify-content:center;align-items:center;font-size:14px;display:flex}.user-box{background:var(--bg-main);border:1px solid var(--border-main);width:100%;height:72px;box-shadow:var(--shadow-elevated);box-sizing:border-box;border-radius:8px;flex-wrap:nowrap;align-items:center;padding:0 12px;transition:all .2s;display:flex;position:relative}.user-box:hover{border-color:var(--primary-color);background:var(--primary-alpha)}.user-box.is-selected{border-color:var(--primary-color);box-shadow:0 0 0 2px var(--primary-alpha)}.user-box.multi-select{cursor:pointer}.user-select{cursor:pointer;flex-shrink:0;justify-content:center;align-items:center;width:18px;height:18px;margin-right:8px;display:inline-flex}.user-select input{opacity:0;pointer-events:none;position:absolute}.user-select-mark{border:1px solid var(--border-main);background:var(--bg-main);width:16px;height:16px;box-shadow:var(--shadow-elevated);border-radius:4px}.memo-container-dark-theme .user-select-mark{background:var(--bg-sub);border-color:var(--text-sub);box-shadow:var(--shadow-dark)}.user-select input:checked+.user-select-mark{border-color:var(--primary-color);background:var(--primary-color);box-shadow:0 0 0 2px var(--primary-alpha)}.user-select input:checked+.user-select-mark:after{content:"";border-bottom:2px solid #fff;border-left:2px solid #fff;width:8px;height:4px;display:block;transform:translate(3px,4px)rotate(-45deg)}.user-avatar-wrapper{border-radius:50%;flex-shrink:0;width:44px;height:44px;margin-right:10px;overflow:hidden}.user-avatar{object-fit:cover;width:100%;height:100%}.user-info-section{flex-direction:column;flex-shrink:0;width:85px;display:flex;position:relative}.user-nickname-section{flex-direction:column;flex:1.5;min-width:0;padding:0 8px;display:flex}.user-nickname-link{color:var(--link-color);white-space:nowrap;text-overflow:ellipsis;font-size:14px;font-weight:600;text-decoration:none;overflow:hidden}.user-nickname-link.is-deleted{color:var(--text-secondary);cursor:not-allowed;opacity:.7;text-decoration:line-through}.user-note-section{flex-direction:column;flex:1;align-items:flex-start;min-width:0;display:flex}.user-info-label{color:var(--text-main);margin-bottom:2px;font-size:12px}.user-id{white-space:nowrap;text-overflow:ellipsis;cursor:pointer;width:100%;font-family:monospace;font-size:12px;transition:background .2s;display:block;overflow:hidden}.user-id.can-expand:hover{z-index:100;background-color:var(--bg-main);width:fit-content;box-shadow:var(--shadow-elevated);border:10px solid #0000;border-radius:4px;margin:-10px;padding:2px 8px;position:absolute;overflow:visible}.user-note-input{width:100%;color:var(--custom-font-color,var(--primary-color));cursor:pointer;background:0 0;border:none;border-bottom:2px dashed #0000;outline:none;padding:0;font-size:13px;transition:all .2s}.user-note-input:hover{border-bottom-color:var(--primary-alpha)}.user-note-input.editing{cursor:text;background:var(--primary-alpha);border-bottom:2px solid var(--primary-color)}@media (max-width:1200px){.panel-users-list{grid-template-columns:repeat(2,1fr)}}@media (max-width:768px){.panel-users-list{grid-template-columns:1fr}.user-box{height:65px}}.memo-container-dark-theme .user-box{background:var(--bg-sub);border-color:var(--border-main);box-shadow:none}.memo-container-dark-theme .user-box:hover{background:var(--bg-sub);border-color:var(--primary-color)}.memo-container-dark-theme .user-nickname-link{color:var(--link-color)}.memo-container-dark-theme .user-info-label,.memo-container-dark-theme .user-id{color:var(--text-sub)}.memo-container-dark-theme .user-id.can-expand:hover{background-color:var(--bg-sub);color:var(--text-inverse);box-shadow:var(--shadow-dark)}.memo-container-dark-theme .user-note-input{color:var(--custom-font-color,var(--primary-color))}.memo-container-dark-theme .user-note-input.editing{background:var(--primary-alpha)}.memo-container-dark-theme .user-select input:checked+.user-select-mark{border-color:var(--primary-color);background:var(--primary-color);box-shadow:0 0 0 2px var(--primary-alpha)}.delete-btn{width:16px;height:16px;color:var(--primary-color);cursor:pointer;z-index:10;position:absolute;top:5px;right:5px}.delete-btn:hover{stroke:var(--danger-color)}');var _GM_addValueChangeListener=(()=>"undefined"!=typeof GM_addValueChangeListener?GM_addValueChangeListener:void 0)(),_GM_getValue=(()=>"undefined"!=typeof GM_getValue?GM_getValue:void 0)(),_GM_registerMenuCommand=(()=>"undefined"!=typeof GM_registerMenuCommand?GM_registerMenuCommand:void 0)(),_GM_setValue=(()=>"undefined"!=typeof GM_setValue?GM_setValue:void 0)(),_unsafeWindow=(()=>"undefined"!=typeof unsafeWindow?unsafeWindow:void 0)();const StyleScope_Minimal=1,StyleScope_Editable=2;class RawRule{constructor(init){Object.assign(this,init);}name;styleScope;aSelector;textSelector;trigger;ignoreProcessed;matchByName;dynamicWatch;uidResolver;get injectMode(){return this.trigger?this.ignoreProcessed?3:2:1}}const isStaticMode=rule=>1===rule.injectMode,isDynamicMode=rule=>2===rule.injectMode,isPollingMode=rule=>3===rule.injectMode,LOG_STYLE="color: white; background: #2196F3; padding: 2px 4px; border-radius: 3px; font-weight: bold;",PREFIX="[Bili-User-Memo]",logger_info=(msg,...args)=>{console.log(`%c${PREFIX}%c`,"background: #9e9e9e; "+LOG_STYLE,"",msg,...args);},logger_error=(msg,...args)=>{console.error(`%c${PREFIX}%c`,"background: #9e9e9e; "+LOG_STYLE,"",msg,...args);},logger_warn=(msg,...args)=>{console.warn(`%c${PREFIX}%c`,"background: #9e9e9e; "+LOG_STYLE,"",msg,...args);},logger_debug=(msg,...args)=>{},DIRECT_UID_ATTRS=["data-user-profile-id","bilisponsor-userid"],SPACE_UID_REGEX=/(?:space\.bilibili\.com|www\.bilibili\.com\/list)\/(\d+)/,UID_STRATEGIES=[function(el){return getAttr(el,"data-bili-uid")||parseUidFromDataId(getAttr(el,"data-id"))||function(el,names){for(const name of names){const value=getAttr(el,name);if(value)return value}return null}(el,DIRECT_UID_ATTRS)},function(el){const root=el.closest("div.bili-dyn-item__main");return root?getAttrFromQuery(root,"[bilisponsor-userid]","bilisponsor-userid")||getAttrFromQuery(root.parentElement,"[data-user-profile-id]","data-user-profile-id")||parseUidFromDataId(getAttrFromQuery(root,"[data-id]","data-id")):null},function(el){logger_debug();const href=el.getAttribute("href")||location.href;if(!href)return null;const match=href.match(SPACE_UID_REGEX);return normalizeUid(match?.[1])}],COMMON_REG=/^https:\/\/[a-z0-9.]+\.bilibili\.com\/.*/,r=rule=>new RawRule(rule),config=[{urlPattern:/^https:\/\/www\.bilibili\.com\/(video|list)\/.*/,rule:r({name:"视频页面",styleScope:StyleScope_Editable,aSelector:".up-name"})},{urlPattern:/^https:\/\/www\.bilibili\.com\/(video|list)\/.*/,rule:r({name:"视频页面-Staff",styleScope:StyleScope_Editable,aSelector:"a.staff-name"})},{urlPattern:/^https:\/\/www\.bilibili\.com\/(video|list)\/.*/,rule:r({name:"视频页面-推荐",styleScope:StyleScope_Minimal,aSelector:".upname a",textSelector:"span.name",trigger:{watch:".rcmd-tab",interval:1e3}})},{urlPattern:/^https:\/\/space\.bilibili\.com\/.*/,rule:r({name:"空间",styleScope:StyleScope_Editable,aSelector:".nickname"})},{urlPattern:/^https:\/\/space\.bilibili\.com\/.*/,rule:r({name:"空间关注/粉丝",styleScope:StyleScope_Editable,aSelector:"a.relation-card-info__uname"})},{urlPattern:/^https:\/\/space\.bilibili\.com\/\d+\/favlist\?(?=[^#]*\bfid=\d+\b)(?=[^#]*\bftype=create\b)[^#]*(?:#.*)?$/,rule:r({name:"空间收藏夹",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__author",textSelector:".bili-video-card__text span[title]",trigger:{watch:".favlist-main",interval:1e3}})},{urlPattern:/^https:\/\/www\.bilibili\.com\/watchlater\/list(?:\?[^#]*)?(?:#.*)?$/,rule:r({name:"稍后再看",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__author",textSelector:".bili-video-card__text span[title]",trigger:{watch:"body",interval:1e3}})},{urlPattern:/^https:\/\/www\.bilibili\.com\/?(?:\?[^#]*)?(?:#.*)?$/,rule:r({name:"首页",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__info--owner, .bili-video-card__author, a.up-name",textSelector:".bili-video-card__info--author, .bili-video-card__text span[title], .up-name__text",trigger:{watch:"#app",interval:1e3}})},{urlPattern:/^https:\/\/search\.bilibili\.com\/(?:all|video|bangumi|pgc|live|article|user)(?:\?[^#]*)?(?:#.*)?$/,rule:r({name:"搜索",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__info--owner, .bili-video-card__author, a.up-name",textSelector:".bili-video-card__info--author, .bili-video-card__text span[title], .up-name__text",trigger:{watch:"#app",interval:1e3}})},{urlPattern:/^https:\/\/www\.bilibili\.com\/v\/popular\/?(?:\?[^#]*)?(?:#.*)?$/,rule:r({name:"热门",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__info--owner, .bili-video-card__author, a.up-name",textSelector:".bili-video-card__info--author, .bili-video-card__text span[title], .up-name__text",trigger:{watch:"#app",interval:1e3}})},{urlPattern:/^https:\/\/www\.bilibili\.com\/v\/[a-z]+\/?(?:\?[^#]*)?(?:#.*)?$/,rule:r({name:"分区",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__info--owner, .bili-video-card__author, a.up-name",textSelector:".bili-video-card__info--author, .bili-video-card__text span[title], .up-name__text",trigger:{watch:"#app",interval:1e3}})},{urlPattern:/^https:\/\/www\.bilibili\.com\/c\/[a-z0-9_-]+\/?(?:\?[^#]*)?(?:#.*)?$/,rule:r({name:"频道",styleScope:StyleScope_Minimal,aSelector:".bili-video-card__info--owner, .bili-video-card__author, a.up-name",textSelector:".bili-video-card__info--author, .bili-video-card__text span[title], .up-name__text",trigger:{watch:"#app",interval:1e3}})},{urlPattern:COMMON_REG,rule:r({name:"评论区",styleScope:StyleScope_Editable,aSelector:"#user-name a",trigger:{watch:"div#contents",interval:1e3},dynamicWatch:true})},{urlPattern:/^https:\/\/message\.bilibili\.com\/(?:[^#]*)?(?:#\/)?whisper(?:\/|$)/,rule:r({name:"私信",styleScope:StyleScope_Minimal,aSelector:'div[data-id^="contact"], div[class^="_ContactName_"]',textSelector:'div[class*="_SessionItem__Name"], div[class^="_ContactName_"]',trigger:{watch:'div[class^="_IM_"]',interval:2e3},ignoreProcessed:true,uidResolver:el=>el.closest('[data-id^="contact_"]')?.getAttribute("data-id")?.split("_")?.[1]||null,matchByName:true})},{urlPattern:/^https:\/\/space\.bilibili\.com\/\d+\/dynamic\/*/,rule:r({name:"个人空间动态",styleScope:StyleScope_Minimal,aSelector:"div.bili-dyn-title span.bili-dyn-title__text",trigger:{watch:".bili-dyn-list",interval:1e3}})},{urlPattern:/^https:\/\/message\.bilibili\.com\/(?:[^#]*)?(?:#\/)?(?:reply|love|at)(?:\/|$)/,rule:r({name:"回复/赞/AT",styleScope:StyleScope_Minimal,aSelector:"a.interaction-item__uname",trigger:{watch:"div.message-content",interval:1e3}})},{urlPattern:/^https:\/\/t\.bilibili\.com\/.*/,rule:r({name:"动态页",styleScope:StyleScope_Editable,textSelector:"span.bili-dyn-title__text",trigger:{watch:"div.bili-dyn-item__main",interval:1e3},dynamicWatch:true,uidResolver:el=>function(el){return String(el.__vue__?.$data.user?.mid??el.__vue__?.$data.mid??null)}(el.closest(".bili-dyn-item"))})},{urlPattern:COMMON_REG,rule:r({name:"最近-UP动态",styleScope:StyleScope_Editable,aSelector:"div.user-name a",trigger:{watch:"div.header-content-panel",interval:1e3}})},{urlPattern:COMMON_REG,rule:r({name:"最近-收藏夹",styleScope:StyleScope_Minimal,aSelector:"span.header-fav-card__info--name",textSelector:"span.header-fav-card__info--name span",trigger:{watch:"div.favorite-panel-popover",interval:1e3}})},{urlPattern:COMMON_REG,rule:r({name:"最近-历史",styleScope:StyleScope_Editable,textSelector:"div.header-history-card__info--name span",trigger:{watch:"div.history-panel-popover",interval:1e3},matchByName:true})},{urlPattern:COMMON_REG,rule:r({name:"最近-正在直播",styleScope:StyleScope_Minimal,aSelector:"a.up-item",textSelector:"div.up-name",trigger:{watch:"div.living-up-list",interval:1e3},matchByName:true})},{urlPattern:/^https:\/\/www\.bilibili\.com\/opus\/\d+/,rule:r({name:"新版动态",styleScope:StyleScope_Editable,aSelector:"div.opus-module-author__name",uidResolver:_el=>{const rawUid=window.__INITIAL_STATE__?.detail?.basic?.uid||window.__INITIAL_STATE__?.detail?.modules?.find(m=>m.module_author)?.module_author?.mid;logger_debug("rawUid",rawUid);return rawUid?String(rawUid):null}})}],DEFAULT_AVATAR_URL="https://i0.hdslb.com/bfs/face/member/noface.jpg@96w_96h_1c_1s.avif",MATCH_BY_NAME_IGNORED_NAMES=new Set(["账号已注销"]),userStore=new class{users=[];_displayMode=2;listeners=new Set;constructor(){this.refreshData();this.listenToRemoteChanges();}refreshData(){const{raw:rawUsers,users:nextUsers}=function(){const raw=getGmValue("biliUsers",[]);return {raw:raw,users:normalizeUsers(raw)}}(),nextDisplayMode=normalizeDisplayMode(getGmValue("displayMode",2)),usersChanged=!usersEqual(this.users,nextUsers),modeChanged=this._displayMode!==nextDisplayMode;this.users=nextUsers;this._displayMode=nextDisplayMode;Array.isArray(rawUsers)&&this.users.length!==rawUsers.length&&saveUsersToStorage(this.users);(usersChanged||modeChanged)&&this.emit({type:"full",users:this.getUsers(),displayMode:this._displayMode,reason:"refresh"});logger_debug(`📊 Store 数据已刷新: 记录数=${this.users.length}, 模式=${this._displayMode}`);}listenToRemoteChanges(){_GM_addValueChangeListener("biliUsers",(_name,_oldValue,newValue,remote)=>{remote&&this.applyRemoteUsers(newValue);});_GM_addValueChangeListener("displayMode",(_name,_oldValue,newValue,remote)=>{remote&&this.applyRemoteDisplayMode(newValue);});}applyRemoteUsers(rawUsers){logger_debug();try{const nextUsers=normalizeUsers(rawUsers),diff=function(previous,next){if(usersEqual(previous,next))return {changedIds:[],hasContentChanges:!1,orderOnly:!1,rescanMatchByName:!1};const previousMap=new Map(previous.map(user=>[user.id,user])),nextMap=new Map(next.map(user=>[user.id,user])),changedIds=new Set;let hasContentChanges=!1,rescanMatchByName=!1;next.forEach(user=>{const existing=previousMap.get(user.id);if(existing){if(!function(a,b){return a.id===b.id&&a.nickname===b.nickname&&a.avatar===b.avatar&&a.memo===b.memo}(existing,user)){changedIds.add(user.id);hasContentChanges=!0;existing.nickname!==user.nickname&&(rescanMatchByName=!0);}}else {changedIds.add(user.id);hasContentChanges=!0;rescanMatchByName=!0;}});previous.forEach(user=>{if(!nextMap.has(user.id)){changedIds.add(user.id);hasContentChanges=!0;}});return {changedIds:Array.from(changedIds),hasContentChanges:hasContentChanges,orderOnly:!hasContentChanges,rescanMatchByName:rescanMatchByName}}(this.users,nextUsers);if(!diff.hasContentChanges&&!diff.orderOnly)return;this.users=nextUsers;if(diff.orderOnly){this.emitUsers("remote");return}this.emitUsers("remote",diff.changedIds,diff.rescanMatchByName);}catch(error){logger_error("同步外部数据失败",error);}}applyRemoteDisplayMode(rawMode){const nextMode=normalizeDisplayMode(rawMode);if(nextMode!==this._displayMode){this._displayMode=nextMode;this.emitDisplayMode("remote");}}get displayMode(){return this._displayMode}getUsers(){return function(users){return users.map(u=>({...u}))}(this.users)}subscribe(listener){this.listeners.add(listener);return ()=>this.listeners.delete(listener)}setDisplayMode(mode){const nextMode=normalizeDisplayMode(mode);if(nextMode!==this._displayMode){this._displayMode=nextMode;!function(mode){setGmValue("displayMode",mode);}(nextMode);this.emitDisplayMode("update");}}ensureUser(uid,originalName){const existing=this.users.find(u=>u.id===uid);return existing||{id:uid,nickname:originalName||uid,avatar:DEFAULT_AVATAR_URL,memo:""}}findUserByName(name){return function(users,name){const trimmedName=name.trim();if(!trimmedName)return {reason:"none"};if(MATCH_BY_NAME_IGNORED_NAMES.has(trimmedName))return {reason:"ignored"};let matchedUser,matchCount=0;users.forEach(user=>{if(user.nickname===trimmedName){matchCount++;1===matchCount&&(matchedUser=user);}});return 0===matchCount?{reason:"none"}:matchCount>1?{reason:"ambiguous"}:{user:matchedUser,reason:"unique"}}(this.users,name).user}updateUser(uid,updates,fallbackName=""){if(!uid)return false;const userIndex=this.findUserIndex(uid),existing=-1===userIndex?null:this.users[userIndex],nextMemo=this.resolveNextMemo(existing,updates);if(!existing)return this.createUserIfNeeded(uid,updates,fallbackName,nextMemo);if(!nextMemo)return this.removeExistingUser(uid,userIndex);const nextNickname=void 0!==updates.nickname?updates.nickname.trim():existing.nickname,nextAvatar=void 0!==updates.avatar?updates.avatar:existing.avatar;if(existing.memo===nextMemo&&existing.nickname===nextNickname&&existing.avatar===nextAvatar)return false;existing.memo=nextMemo;existing.nickname=nextNickname||uid;existing.avatar=nextAvatar;this.commitUsers("update",[uid]);logger_info(`📝 备注已更新 | UID:${uid} -> ${nextMemo}`);return true}updateUserMemo(uid,newMemo,fallbackName=""){return this.updateUser(uid,{memo:newMemo},fallbackName)}findUserIndex(uid){return this.users.findIndex(u=>u.id===uid)}resolveNextMemo(existing,updates){return void 0!==updates.memo?updates.memo.trim():(existing?.memo||"").trim()}createUserIfNeeded(uid,updates,fallbackName,nextMemo){if(!nextMemo)return false;this.users.push({id:uid,nickname:(updates.nickname||fallbackName||uid).trim(),avatar:updates.avatar??getUserAvatarFromDOM(uid),memo:nextMemo});this.commitUsers("update",[uid]);logger_info(`📝 备注已更新 | UID:${uid} -> ${nextMemo}`);return true}removeExistingUser(uid,userIndex){this.users.splice(userIndex,1);this.commitUsers("remove",[uid]);logger_info(`🗑️ 备注清空,已删除用户记录 | UID:${uid}`);return true}removeUser(uid){if(!uid)return false;const index=this.users.findIndex(u=>u.id===uid);if(-1===index)return false;this.users.splice(index,1);this.commitUsers("remove",[uid]);return true}removeUsers(ids){const idSet=new Set(ids.filter(Boolean));if(0===idSet.size)return 0;const before=this.users.length;this.users=this.users.filter(u=>!idSet.has(u.id));const removed=before-this.users.length;removed>0&&this.commitUsers("remove",Array.from(idSet));return removed}upsertImportedUsers(importedUsers){const normalized=normalizeUsers(importedUsers);if(0===normalized.length)return {added:0,updated:0};let added=0,updated=0;const changedIds=[],userMap=new Map(this.users.map(u=>[u.id,u]));normalized.forEach(incoming=>{const existing=userMap.get(incoming.id);if(!existing){this.users.push({...incoming});userMap.set(incoming.id,this.users[this.users.length-1]);added++;changedIds.push(incoming.id);return}let finalAvatar=incoming.avatar;incoming.avatar===DEFAULT_AVATAR_URL&&existing.avatar!==DEFAULT_AVATAR_URL&&(finalAvatar=existing.avatar);if(existing.nickname!==incoming.nickname||existing.avatar!==finalAvatar||existing.memo!==incoming.memo||existing.isDeleted!==incoming.isDeleted){existing.nickname=incoming.nickname;existing.avatar=finalAvatar;existing.memo=incoming.memo;void 0!==incoming.isDeleted&&(existing.isDeleted=incoming.isDeleted);updated++;changedIds.push(incoming.id);}});(added>0||updated>0)&&this.commitUsers("import",changedIds,true);return {added:added,updated:updated}}updateUserProfiles(profiles){if(0===profiles.length)return 0;let updatedCount=0;const changedIds=[],userMap=new Map(this.users.map(u=>[u.id,u]));profiles.forEach(profile=>{const target=userMap.get(profile.id);if(!target)return;let finalAvatar=profile.avatar;profile.avatar===DEFAULT_AVATAR_URL&&target.avatar!==DEFAULT_AVATAR_URL&&(finalAvatar=target.avatar);if(target.nickname!==profile.nickname||target.avatar!==finalAvatar||target.isDeleted!==profile.isDeleted){target.nickname=profile.nickname||target.nickname;target.avatar=finalAvatar;void 0!==profile.isDeleted&&(target.isDeleted=profile.isDeleted);updatedCount++;changedIds.push(profile.id);}});updatedCount>0&&this.commitUsers("profile",changedIds);return updatedCount}commitUsers(reason,changedIds=[],rescanMatchByName="import"===reason){saveUsersToStorage(this.users);this.emitUsers(reason,changedIds,rescanMatchByName);}emitUsers(reason,changedIds=[],rescanMatchByName=false){this.emit({type:"users",users:this.getUsers(),reason:reason,changedIds:changedIds,rescanMatchByName:rescanMatchByName});}emitDisplayMode(reason){this.emit({type:"displayMode",displayMode:this._displayMode,reason:reason});}emit(change){this.listeners.forEach(listener=>{try{listener(change);}catch(error){logger_error("UserStore 监听器执行失败",error);}});}},BILI_MEMO_OWNED_SELECTOR="[data-bili-memo-owned]",GLOBAL_STYLE_SHEET=new CSSStyleSheet;GLOBAL_STYLE_SHEET.replaceSync(".editable-textarea{font-size:var(--auto-detected-font-size,13px);min-width:2ch;color:var(--memo-textarea-color);white-space:nowrap;background:var(--memo-textarea-bg);border:none;border-bottom:2px solid var(--memo-textarea-border-color);text-shadow:0 1px 2px var(--overlay);opacity:.85;border-radius:6px 6px 0 0;outline:none;margin-right:8px;padding:4px 6px;transition:border-color .2s,background .2s,opacity .2s;display:inline-block}.editable-textarea:hover{opacity:1;background:color-mix(in srgb, var(--memo-textarea-bg), white 20%)}.bili-memo-tag{cursor:pointer;vertical-align:middle;color:var(--memo-tag-color);font-size:inherit;display:inline}.bili-memo-input{background:var(--bg-main);border:1px solid var(--primary-color);font-size:var(--auto-detected-font-size,13px);height:calc(var(--auto-detected-font-size,14px) + 6px);line-height:calc(var(--auto-detected-font-size,14px) + 6px);vertical-align:middle;color:var(--memo-input-color);border-radius:4px;outline:none;margin-left:4px;padding:0 4px}");let CUSTOM_MEMO_STYLE_SHEET=null;const fontSizeCache=new class{cache=new Map;generateCacheKey(element,rule){if(rule){const parts=[];rule.aSelector&&parts.push(`a:${rule.aSelector}`);rule.textSelector&&parts.push(`t:${rule.textSelector}`);if(parts.length>0)return parts.join("|")}const fallbackParts=[];element.id&&fallbackParts.push(`id:${element.id}`);if(element.className&&"string"==typeof element.className){const classes=element.className.split(/\s+/).filter(Boolean).sort();classes.length>0&&fallbackParts.push(`class:${classes.join(".")}`);}if(0===fallbackParts.length){logger_debug("[FontCache]",element.tagName,"→","(no cache key)");return ""}return fallbackParts.join(".")}getOrDetect(element,rule){const cacheKey=this.generateCacheKey(element,rule);if(!cacheKey)return getComputedStyle(element).fontSize;const cached=this.cache.get(cacheKey);if(cached){logger_debug("[FontCache] ✓",cacheKey,"=",cached);return cached}const fontSize=getComputedStyle(element).fontSize;this.cache.set(cacheKey,fontSize);logger_debug("[FontCache] ✗",cacheKey,"→",fontSize);return fontSize}},wrapperCache=new WeakMap;class DynamicRuleWatcher{constructor(rule,onTrigger){this.rule=rule;this.onTrigger=onTrigger;}static originalAttachShadow=Element.prototype.attachShadow;static attachShadowPatched=false;static attachShadowListeners=new Set;legacyObserver=null;legacyPollTimer=null;legacyIdlePending=false;discoveryObservers=new Map;instanceObservers=new Map;instanceIdlePending=new WeakSet;handleShadowAttached=shadowRoot=>{this.observeDiscoveryScope(shadowRoot);this.scanAndAttachNewTargets();};start(){this.rule.dynamicWatch?this.startGlobalWatch():this.tryAttachOrPollLegacy();}stop(){if(this.legacyPollTimer){clearInterval(this.legacyPollTimer);this.legacyPollTimer=null;}if(this.legacyObserver){this.legacyObserver.disconnect();this.legacyObserver=null;}this.legacyIdlePending=false;this.unregisterAttachShadowListener();this.discoveryObservers.forEach(observer=>observer.disconnect());this.discoveryObservers.clear();this.instanceObservers.forEach(({observer:observer})=>observer.disconnect());this.instanceObservers.clear();}startGlobalWatch(){logger_debug(`📡 启动动态全域监听: [${this.rule.name}] watch=${this.rule.trigger.watch}`);this.registerAttachShadowListener();this.observeDiscoveryScope(document);this.scanAndAttachNewTargets();}static ensureAttachShadowPatched(){if(DynamicRuleWatcher.attachShadowPatched)return;const originalAttachShadow=DynamicRuleWatcher.originalAttachShadow;Element.prototype.attachShadow=function(init){const shadowRoot=originalAttachShadow.call(this,init);for(const listener of DynamicRuleWatcher.attachShadowListeners)try{listener(shadowRoot);}catch(error){logger_debug("attachShadow listener error",error);}return shadowRoot};DynamicRuleWatcher.attachShadowPatched=true;}registerAttachShadowListener(){DynamicRuleWatcher.ensureAttachShadowPatched();DynamicRuleWatcher.attachShadowListeners.add(this.handleShadowAttached);}unregisterAttachShadowListener(){DynamicRuleWatcher.attachShadowListeners.delete(this.handleShadowAttached);}observeDiscoveryScope(scope){if(this.discoveryObservers.has(scope))return;const observer=new MutationObserver(mutations=>{const{hasAddedNodes:hasAddedNodes,hasRemovedNodes:hasRemovedNodes}=shouldHandleDiscoveryMutations(mutations);if(hasAddedNodes){this.scanAndAttachNewTargets();this.bridgeShadowMutationsToWatchScopes(scope);}if(hasRemovedNodes){this.cleanupDetachedTargets();this.cleanupDetachedDiscoveryScopes();}});observer.observe(scope,{childList:true,subtree:true});this.discoveryObservers.set(scope,observer);this.discoverShadowScopes(scope);}discoverShadowScopes(scope){scope.querySelectorAll("*").forEach(element=>this.observeHostShadowScope(element));}observeHostShadowScope(element){const shadowRoot=element.shadowRoot;shadowRoot&&this.observeDiscoveryScope(shadowRoot);}scanAndAttachNewTargets(){const targets=function(selector){return querySelectorAllDeep(selector)}(this.rule.trigger.watch);0!==targets.length&&targets.forEach(target=>{const scope=resolveWatchScope(target),keyNode=target,current=this.instanceObservers.get(keyNode);if(current){if(current.scope!==scope){logger_debug(`🔁 [${this.rule.name}] 容器作用域切换,重绑监听`,target);current.observer.disconnect();this.attachInstanceWatcher(keyNode,scope);}}else {logger_debug(`🔭 [${this.rule.name}] 捕获新容器实例`,target);this.attachInstanceWatcher(keyNode,scope);}});}createScopeObserver(keyNode,scope){const observer=new MutationObserver(mutations=>{if(shouldHandleDiscoveryMutations(mutations).hasAddedNodes&&!this.instanceIdlePending.has(keyNode)){this.instanceIdlePending.add(keyNode);this.onTrigger(this.rule,scope);this.instanceIdlePending.delete(keyNode);}});observer.observe(scope,{childList:true,subtree:true});return observer}bridgeShadowMutationsToWatchScopes(scope){if(scope instanceof ShadowRoot&&0!==this.instanceObservers.size)for(const{scope:watchScope}of this.instanceObservers.values())watchScope instanceof ShadowRoot&&watchScope===scope||isNodeInsideScope(scope,watchScope)&&this.onTrigger(this.rule,watchScope);}attachInstanceWatcher(keyNode,scope){const observer=this.createScopeObserver(keyNode,scope);this.instanceObservers.set(keyNode,{observer:observer,scope:scope});this.onTrigger(this.rule,scope);}cleanupDetachedTargets(){for(const[node,{observer:observer}]of this.instanceObservers)if(!node.isConnected){logger_debug(`🗑️ [${this.rule.name}] 容器已销毁,移除监听器`);observer.disconnect();this.instanceObservers.delete(node);}}cleanupDetachedDiscoveryScopes(){for(const[scope,observer]of this.discoveryObservers)if(scope!==document&&!scope.isConnected){observer.disconnect();this.discoveryObservers.delete(scope);}}tryAttachOrPollLegacy(){this.attachLegacy()||this.legacyPollTimer||(this.legacyPollTimer=window.setInterval(()=>{if(this.attachLegacy()){this.legacyPollTimer&&clearInterval(this.legacyPollTimer);this.legacyPollTimer=null;logger_debug(`👀 规则 [${this.rule.name}] 监听器挂载成功`);}},2*this.rule.trigger.interval));}attachLegacy(){const watchTarget=getWatchTarget(this.rule.trigger.watch);if(!watchTarget)return false;const scope=resolveWatchScope(watchTarget);this.legacyObserver=this.createIdleLegacyObserver(scope);this.onTrigger(this.rule,scope);return true}createIdleLegacyObserver(scope){const scheduleTrigger=()=>{if(!this.legacyIdlePending){this.legacyIdlePending=true;requestIdle(()=>{this.legacyIdlePending=false;this.onTrigger(this.rule,scope);},this.rule.trigger.interval);}},observer=new MutationObserver(mutations=>{shouldHandleDiscoveryMutations(mutations).hasAddedNodes&&scheduleTrigger();});observer.observe(scope,{childList:true,subtree:true});return observer}}class PollingRuleWatcher{constructor(rule,onTrigger){this.rule=rule;this.onTrigger=onTrigger;}pollTimer=null;start(){logger_debug(`⏱️ 轮询规则启动: [${this.rule.name}] interval=${this.rule.trigger.interval}ms watch=${this.rule.trigger.watch}`);this.tick();this.pollTimer=window.setInterval(()=>this.tick(),this.rule.trigger.interval);}stop(){if(this.pollTimer){clearInterval(this.pollTimer);this.pollTimer=null;}logger_debug(`🛑 轮询规则停止: [${this.rule.name}]`);}tick(){const watchTarget=getWatchTarget(this.rule.trigger.watch);if(!watchTarget)return;const scope=resolveWatchScope(watchTarget);this.onTrigger(this.rule,scope);}}class RemoteChangeBuffer{changedIds=new Set;rescanMatchByName=false;needsFullRefresh=false;displayModeChanged=false;queue(change){if("displayMode"!==change.type){if("users"===change.type){this.rescanMatchByName||=Boolean(change.rescanMatchByName);change.changedIds&&0!==change.changedIds.length?change.changedIds.forEach(id=>{id&&this.changedIds.add(id);}):this.needsFullRefresh=true;}}else this.displayModeChanged=true;}consume(){if(!this.needsFullRefresh&&0===this.changedIds.size&&!this.rescanMatchByName&&!this.displayModeChanged)return null;const snapshot={changedIds:Array.from(this.changedIds),needsFullRefresh:this.needsFullRefresh,rescanMatchByName:this.rescanMatchByName,displayModeChanged:this.displayModeChanged};this.changedIds.clear();this.rescanMatchByName=false;this.needsFullRefresh=false;this.displayModeChanged=false;return snapshot}}class RuleScanScheduler{constructor(processRule,isActive){this.processRule=processRule;this.isActive=isActive;}staticRetryTimers=[];staticRetryToken=0;ruleDebounceTimers=new Map;dispose(){this.clearStaticRuleRetries();for(const rule of this.ruleDebounceTimers.keys())this.clearRuleDebounceTimers(rule);}scanRules(rules,scope,source="scan rules"){if(0===rules.length)return;const queue=[...rules],runChunk=deadline=>{(async()=>{for(;queue.length>0&&deadline.timeRemaining()>1;){const rule=queue.shift();rule&&await this.processRule(rule,scope);}queue.length>0&&requestIdle(runChunk);})();};requestIdle(runChunk);}scheduleStaticRuleRetries(staticRules,scope){this.clearStaticRuleRetries();if(0===staticRules.length)return;const token=++this.staticRetryToken;[350,900].forEach(delay2=>{const timerId=window.setTimeout(()=>{this.isActive()&&token===this.staticRetryToken&&this.scanRules(staticRules,scope,`static retry ${delay2}ms`);},delay2);this.staticRetryTimers.push(timerId);});}clearStaticRuleRetries(){this.staticRetryToken++;this.staticRetryTimers.forEach(timerId=>clearTimeout(timerId));this.staticRetryTimers=[];}scheduleDynamicRuleScan(rule,delay2,scope){let scopeTimers=this.ruleDebounceTimers.get(rule);if(!scopeTimers){scopeTimers=new Map;this.ruleDebounceTimers.set(rule,scopeTimers);}const existingTimer=scopeTimers.get(scope);existingTimer&&clearTimeout(existingTimer);const timerId=window.setTimeout(()=>{const activeScopeTimers=this.ruleDebounceTimers.get(rule);activeScopeTimers?.delete(scope);activeScopeTimers&&0===activeScopeTimers.size&&this.ruleDebounceTimers.delete(rule);this.scanRules([rule],scope,"dynamic debounce");},delay2);scopeTimers.set(scope,timerId);}clearRuleDebounceTimers(rule){const scopeTimers=this.ruleDebounceTimers.get(rule);if(scopeTimers){scopeTimers.forEach(timerId=>clearTimeout(timerId));this.ruleDebounceTimers.delete(rule);}}}class PageInjector{domReady=false;lastUrl="";pendingRemoteChanges=new RemoteChangeBuffer;scanScheduler=new RuleScanScheduler((rule,scope)=>this.scanAndInjectRule(rule,scope),()=>this.domReady);activeWatchers=new Map;activePollingWatchers=new Map;constructor(){logger_info("🚀 PageInjector 正在启动...");userStore.subscribe(change=>this.handleStoreChange(change));document.addEventListener("visibilitychange",()=>this.handleVisibilityChange());this.startUrlMonitor();this.onDomReady(async()=>{await this.waitForBiliEnvironment();await delay(100);this.domReady=true;this.handleUrlChange();});}refreshData(){userStore.refreshData();this.domReady&&this.scanActiveRules(document);}handleStoreChange(change){if(this.domReady)if(this.shouldDeferRemoteChange(change))this.queuePendingRemoteChange(change);else if("displayMode"!==change.type)if("users"!==change.type)this.refreshRenderedNodes(change.users,change.displayMode);else {this.refreshRenderedNodes(change.users,userStore.displayMode,change.changedIds);change.rescanMatchByName&&this.scanMatchByNameRules(document);}else this.refreshRenderedNodes(userStore.getUsers(),change.displayMode);}shouldDeferRemoteChange(change){return "remote"===change.reason&&"visible"!==document.visibilityState}queuePendingRemoteChange(change){this.pendingRemoteChanges.queue(change);}handleVisibilityChange(){"visible"===document.visibilityState&&this.domReady&&this.flushPendingRemoteChanges();}flushPendingRemoteChanges(){const pendingState=this.pendingRemoteChanges.consume();if(!pendingState)return;const currentUrl=_unsafeWindow.location.href;if(currentUrl!==this.lastUrl){this.lastUrl=currentUrl;logger_debug();this.handleUrlChange();}const users=userStore.getUsers(),displayMode=userStore.displayMode,needsFullRefresh=pendingState.needsFullRefresh||pendingState.displayModeChanged,changedIds=pendingState.changedIds;needsFullRefresh?this.refreshRenderedNodes(users,displayMode):changedIds.length>0&&this.refreshRenderedNodes(users,displayMode,changedIds);pendingState.rescanMatchByName&&this.scanMatchByNameRules(document);}refreshRenderedNodes(users,displayMode,changedIds){!function(users,displayMode,changedIds){if(changedIds&&changedIds.length>0){const uniqueIds=Array.from(new Set(changedIds.filter(Boolean))),targetIdSet=new Set(uniqueIds),userMap2=new Map;users.forEach(user=>{targetIdSet.has(user.id)&&userMap2.set(user.id,user);});uniqueIds.forEach(uid=>{const tags=querySelectorAllDeep(`[data-bili-uid="${function(value){return "undefined"!=typeof CSS&&"function"==typeof CSS.escape?CSS.escape(value):value.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}(uid)}"]`),user=userMap2.get(uid);tags.forEach(tag=>refreshTag(tag,user,displayMode));});return}const userMap=new Map(users.map(u=>[u.id,u]));querySelectorAllDeep("[data-bili-uid]").forEach(tag=>{const uid=tag.getAttribute("data-bili-uid");uid&&refreshTag(tag,userMap.get(uid),displayMode);});}(users,displayMode,changedIds);}scanActiveRules(scope){const activeRules=[...this.activeWatchers.keys(),...this.activePollingWatchers.keys()];0!==activeRules.length&&this.scanScheduler.scanRules(activeRules,scope,"refresh active rules");}startUrlMonitor(){this.lastUrl=_unsafeWindow.location.href;window.setInterval(()=>{const currentUrl=_unsafeWindow.location.href;if(currentUrl!==this.lastUrl){this.lastUrl=currentUrl;logger_debug();this.handleUrlChange();}},1e3);}handleUrlChange(){if(!this.domReady)return;const matchedRules=function(currentUrl=_unsafeWindow.location.href){return config.filter(entry=>entry.urlPattern.test(currentUrl)).map(entry=>entry.rule)}(),groups=this.groupRulesByMode(matchedRules);this.applyStaticRules(groups.staticRules,document);this.reconcileWatchers(groups.dynamicRules);this.reconcilePollingWatchers(groups.pollingRules);}groupRulesByMode(rules){return function(rules){return rules.reduce((groups,rule)=>{isStaticMode(rule)?groups.staticRules.push(rule):isDynamicMode(rule)?groups.dynamicRules.push(rule):isPollingMode(rule)&&groups.pollingRules.push(rule);return groups},{staticRules:[],dynamicRules:[],pollingRules:[]})}(rules)}applyStaticRules(staticRules,scope){if(0!==staticRules.length){this.scanScheduler.scanRules(staticRules,scope,"static initial scan");this.scanScheduler.scheduleStaticRuleRetries(staticRules,scope);}else this.scanScheduler.clearStaticRuleRetries();}reconcileWatchers(nextRules){for(const[rule,watcher]of this.activeWatchers)if(!nextRules.includes(rule)){watcher.stop();this.scanScheduler.clearRuleDebounceTimers(rule);this.activeWatchers.delete(rule);}nextRules.forEach(rule=>{if(this.activeWatchers.has(rule))return;const watcher=new DynamicRuleWatcher(rule,(r2,scope)=>{this.scanScheduler.scheduleDynamicRuleScan(r2,r2.trigger.interval,scope);});this.activeWatchers.set(rule,watcher);watcher.start();});}reconcilePollingWatchers(nextRules){for(const[rule,watcher]of this.activePollingWatchers)if(!nextRules.includes(rule)){watcher.stop();this.activePollingWatchers.delete(rule);}nextRules.forEach(rule=>{if(this.activePollingWatchers.has(rule))return;const watcher=new PollingRuleWatcher(rule,(r2,scope)=>{this.scanScheduler.scanRules([r2],scope,"polling tick");});this.activePollingWatchers.set(rule,watcher);watcher.start();});}scanMatchByNameRules(scope){const rules=function(rules){return Array.from(rules).filter(rule=>Boolean(rule.matchByName))}([...this.activeWatchers.keys(),...this.activePollingWatchers.keys()]);0!==rules.length&&this.scanScheduler.scanRules(rules,scope,"matchByName rescan");}async scanAndInjectRule(rule,scope){const selector=function(rule){const baseSelector=rule.aSelector||rule.textSelector;return baseSelector?rule.ignoreProcessed?baseSelector:`${baseSelector}:not([data-bili-processed])`:null}(rule);if(!selector)return;const elements=scope instanceof ShadowRoot?querySelectorAllDeep(selector).filter(element=>isNodeInsideScope(element,scope)):querySelectorAllDeep(selector,scope);!function(rule,selector,count){0!==count&&(isStaticMode(rule)?logger_debug():isPollingMode(rule)&&logger_debug(`🔁 轮询注入 [${rule.name}]: 找到 ${count} 个目标元素`));}(rule,selector,elements.length);0!==elements.length&&elements.forEach(el=>{this.applyRuleToElement(el,rule);});}async applyRuleToElement(el,rule){let uidResolved=false,applied=false;try{if(el.classList.contains("editable-textarea")){el.setAttribute("data-bili-processed","true");return}const originalName=function(el,rule){return readPreferredText(resolveRuleTextTarget(el,rule))||readPreferredText(el)||""}(el,rule),uid=this.resolveElementUid(el,rule,originalName);uidResolved=Boolean(uid);if(!uid)return;const user=userStore.ensureUser(uid,originalName);applied=await async function(el,user,rule,meta){const displayMode=userStore.displayMode;switch(rule.styleScope){case StyleScope_Minimal:return function(element,user,meta,displayMode){if(!element)return !1;ensureStylesForElement(element);syncRenderedNodeState(element,user,meta.originalName,displayMode);syncElementMeta(element,meta);return !0}(resolveRuleTextTarget(el,rule),user,meta,displayMode);case StyleScope_Editable:return function(el,user,rule,meta,displayMode){let wrapper=wrapperCache.get(el);if(!wrapper&&el.nextElementSibling?.classList.contains("editable-textarea")){wrapper=el.nextElementSibling;wrapperCache.set(el,wrapper);}if(!wrapper){wrapper=markOwnedElement(document.createElement("span"));wrapper.classList.add("editable-textarea");wrapper.setAttribute("data-bili-processed","true");wrapper.addEventListener("click",e=>{e.stopPropagation();e.preventDefault();const uid=wrapper?.dataset.biliUid,originalName=wrapper?.dataset.biliOriginal||meta.originalName;if(!uid)return;const latestUser=userStore.ensureUser(uid,originalName);!function(targetElement,user){function autoResize(input2){input2.style.width="0px";input2.style.width=input2.scrollWidth+1+"px";}if(!user||targetElement.querySelector("input.bili-memo-input"))return;const originalName=targetElement.dataset.biliOriginal||targetElement.textContent||"",currentMemo=user.memo||originalName,input=markOwnedElement(document.createElement("input"));input.type="text";input.value=currentMemo;input.className="bili-memo-input";input.translate=!1;input.maxLength=24;const detectedFontSize=targetElement.style.getPropertyValue("--auto-detected-font-size");detectedFontSize&&input.style.setProperty("--auto-detected-font-size",detectedFontSize);const parent=targetElement.parentElement;if(!parent)return;targetElement.style.display="none";parent.insertBefore(input,targetElement.nextSibling);input.focus();let exited=!1;const saveAndExit=shouldSave=>{if(exited)return;exited=!0;const newValue=input.value.trim();input.remove();targetElement.style.display="";if(shouldSave&&newValue!==currentMemo){userStore.updateUserMemo(user.id,newValue,originalName);syncRenderedNodeState(targetElement,{...user,memo:newValue},originalName,userStore.displayMode,{isEditableWrapper:targetElement.classList.contains("editable-textarea")});}};input.addEventListener("keydown",e=>{if(!e.isComposing)if("Enter"===e.key){e.preventDefault();saveAndExit(!0);}else if("Escape"===e.key){e.preventDefault();saveAndExit(!1);}});input.addEventListener("blur",()=>saveAndExit(!0));input.addEventListener("click",e=>e.stopPropagation());input.addEventListener("input",()=>{if(input.value.length>=input.maxLength){input.setCustomValidity("已达到最大长度:24 字符");input.reportValidity();}else input.setCustomValidity("");autoResize(input);});autoResize(input);}(wrapper,latestUser);});el.style.display="none";el.insertAdjacentElement("afterend",wrapper);wrapperCache.set(el,wrapper);}syncRenderedNodeState(wrapper,user,meta.originalName,displayMode,{isEditableWrapper:!0});const detectedSize=fontSizeCache.getOrDetect(el,rule);detectedSize&&wrapper.style.setProperty("--auto-detected-font-size",detectedSize);syncElementMeta(wrapper,meta);ensureStylesForElement(wrapper);return !0}(el,user,rule,meta,displayMode);default:logger_warn(`⚠️ 不支持的样式作用域: ${rule.styleScope}`);return !1}}(el,user,rule,{uid:uid,originalName:originalName});applied&&el.setAttribute("data-bili-processed","true");}finally{}}resolveElementUid(el,rule,originalName){if(rule.matchByName&&originalName)return userStore.findUserByName(originalName)?.id||null;if(rule.uidResolver){const uid2=rule.uidResolver(el,rule);if(uid2)return uid2}const uid=function(el,silent=false){for(const strategy of UID_STRATEGIES){const uid=strategy(el);if(uid)return uid}silent||logger_warn("⚠️ 无法从元素中提取 UID:",el);return null}(el,Boolean(rule.matchByName));return uid||null}onDomReady(callback){"complete"!==document.readyState&&"interactive"!==document.readyState?window.addEventListener("DOMContentLoaded",()=>callback(),{once:true}):callback();}async waitForBiliEnvironment(){await async function(predicate,{intervalMs:intervalMs=50,timeoutMs:timeoutMs}={}){const startTime=Date.now();for(;;){if(await predicate())return true;if(void 0!==timeoutMs&&Date.now()-startTime>=timeoutMs)return false;await delay(intervalMs);}}(()=>Boolean(_unsafeWindow.__VUE__));}}let pageInjector=null;const gmPersistStorage=function(prefix,emptyValue=""){return {getItem:storageKey=>getGmValue(`${prefix}${storageKey}`,emptyValue)||null,setItem(storageKey,value){setGmValue(`${prefix}${storageKey}`,value);},removeItem(storageKey){setGmValue(`${prefix}${storageKey}`,emptyValue);}}}("panelPrefs:"),UID=string(),UserSchema=object({id:UID,nickname:string(),avatar:optional(string()),memo:string()}),UserSchemaOld=object({bid:UID,nickname:string(),memo:string(),avatar:optional(string()),info:string()}),CombinedSchema=union([array(UserSchema),record(UID,UserSchemaOld)]);class ResImpl{constructor(body,init){this.rawBody=body;this.init=init;this.body=body.stream();const{headers:headers,statusCode:statusCode,statusText:statusText,finalUrl:finalUrl,redirected:redirected}=init;this.headers=headers;this.status=statusCode;this.statusText=statusText;this.url=finalUrl;this.type="basic";this.redirected=redirected;this._bodyUsed=false;}get bodyUsed(){return this._bodyUsed}get ok(){return this.status<300}arrayBuffer(){if(this.bodyUsed)throw new TypeError("Failed to execute 'arrayBuffer' on 'Response': body stream already read");this._bodyUsed=true;return this.rawBody.arrayBuffer()}blob(){if(this.bodyUsed)throw new TypeError("Failed to execute 'blob' on 'Response': body stream already read");this._bodyUsed=true;return Promise.resolve(this.rawBody.slice(0,this.rawBody.size,this.rawBody.type))}clone(){if(this.bodyUsed)throw new TypeError("Failed to execute 'clone' on 'Response': body stream already read");return new ResImpl(this.rawBody,this.init)}formData(){if(this.bodyUsed)throw new TypeError("Failed to execute 'formData' on 'Response': body stream already read");this._bodyUsed=true;return this.rawBody.text().then(decode)}async json(){if(this.bodyUsed)throw new TypeError("Failed to execute 'json' on 'Response': body stream already read");this._bodyUsed=true;return JSON.parse(await this.rawBody.text())}text(){if(this.bodyUsed)throw new TypeError("Failed to execute 'text' on 'Response': body stream already read");this._bodyUsed=true;return this.rawBody.text()}async bytes(){if(this.bodyUsed)throw new TypeError("Failed to execute 'bytes' on 'Response': body stream already read");this._bodyUsed=true;return new Uint8Array(await this.rawBody.arrayBuffer())}}const httpMethods=["GET","POST","PUT","DELETE","PATCH","HEAD","TRACE","OPTIONS","CONNECT"];class Node{value;next;constructor(value){this.value=value;}}class Queue{#head;#tail;#size;constructor(){this.clear();}enqueue(value){const node=new Node(value);if(this.#head){this.#tail.next=node;this.#tail=node;}else {this.#head=node;this.#tail=node;}this.#size++;}dequeue(){const current=this.#head;if(current){this.#head=this.#head.next;this.#size--;this.#head||(this.#tail=void 0);return current.value}}peek(){if(this.#head)return this.#head.value}clear(){this.#head=void 0;this.#tail=void 0;this.#size=0;}get size(){return this.#size}*[Symbol.iterator](){let current=this.#head;for(;current;){yield current.value;current=current.next;}}*drain(){for(;this.#head;)yield this.dequeue();}}const limit=function(concurrency){let rejectOnClear=false;"object"==typeof concurrency&&({concurrency:concurrency,rejectOnClear:rejectOnClear=false}=concurrency);validateConcurrency(concurrency);if("boolean"!=typeof rejectOnClear)throw new TypeError("Expected `rejectOnClear` to be a boolean");const queue=new Queue;let activeCount=0;const resumeNext=()=>{if(activeCount0){activeCount++;queue.dequeue().run();}},run=async(function_,resolve,arguments_)=>{const result=(async()=>function_(...arguments_))();resolve(result);try{await result;}catch{}(()=>{activeCount--;resumeNext();})();},generator=(function_,...arguments_)=>new Promise((resolve,reject)=>{((function_,resolve,reject,arguments_)=>{const queueItem={reject:reject};new Promise(internalResolve=>{queueItem.run=internalResolve;queue.enqueue(queueItem);}).then(run.bind(void 0,function_,resolve,arguments_));activeCountactiveCount},pendingCount:{get:()=>queue.size},clearQueue:{value(){if(!rejectOnClear){queue.clear();return}const abortError=AbortSignal.abort().reason;for(;queue.size>0;)queue.dequeue().reject(abortError);}},concurrency:{get:()=>concurrency,set(newConcurrency){validateConcurrency(newConcurrency);concurrency=newConcurrency;queueMicrotask(()=>{for(;activeCount0;)resumeNext();});}},map:{async value(iterable,function_){const promises=Array.from(iterable,(value,index)=>this(function_,value,index));return Promise.all(promises)}}});return generator}(2),MIXIN_KEY_ENC_TAB=[46,47,18,2,53,8,23,32,15,50,10,31,58,3,45,35,27,43,5,49,33,9,42,19,29,28,14,39,12,38,41,13,37,48,7,16,24,55,40,61,26,17,0,1,60,51,30,4,22,25,54,21,56,59,6,63,57,62,11,36,20,34,44,52],getUserInfo=function(fn,{ttlMs:ttlMs,getKey:getKey=(...args)=>JSON.stringify(args)}){const cache=new Map;return async(...args)=>{const cacheKey=getKey(...args),cached=cache.get(cacheKey),now=Date.now();if(cached&&now-cached.timestamplimit(async()=>{await new Promise(resolve=>setTimeout(resolve,300+500*Math.random()));return async function(mid){try{const{img_key:img_key,sub_key:sub_key}=await async function(){const cache=function(){const cache=getGmValue("bili_wbi_keys",null);return cache?Date.now()-cache.timestamp>=36e5?null:cache:null}();if(cache)return {img_key:cache.img_key,sub_key:cache.sub_key};try{const res=await GM_fetch("https://api.bilibili.com/x/web-interface/nav",{headers:{Referer:"https://www.bilibili.com/"}}),json=await res.json(),{img_url:img_url,sub_url:sub_url}=json.data.wbi_img,keys={img_key:img_url.slice(img_url.lastIndexOf("/")+1,img_url.lastIndexOf(".")),sub_key:sub_url.slice(sub_url.lastIndexOf("/")+1,sub_url.lastIndexOf("."))};!function(key,value,timestamp=Date.now()){setGmValue(key,{...value,timestamp:timestamp});}("bili_wbi_keys",keys);return keys}catch(err){logger_error("Failed to fetch WBI keys",err);throw new Error("WBI key 初始化失败")}}(),url=`https://api.bilibili.com/x/space/wbi/acc/info?${function(params,img_key,sub_key){const mixin_key=(orig=>MIXIN_KEY_ENC_TAB.map(n=>orig[n]).join("").slice(0,32))(img_key+sub_key),curr_time=Math.round(Date.now()/1e3),chr_filter=/[!'()*]/g,signedParams={...params,wts:curr_time},query=Object.entries(signedParams).sort(([a],[b])=>a.localeCompare(b)).map(([key,value])=>{const filteredValue=String(value).replace(chr_filter,"");return `${encodeURIComponent(key)}=${encodeURIComponent(filteredValue)}`}).join("&");return `${query}&w_rid=${(message=>{const buffer=(new TextEncoder).encode(message),n=buffer.length,words=new Uint32Array(1+(n+8>>6)<<4);for(let i=0;i>2]|=buffer[i]<>2]|=128<4294967296*Math.abs(Math.sin(i+1))>>>0),S=[7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21],rotl=(x,n2)=>x<>>32-n2;for(let i=0;iview.setUint32(4*i,val,!0));return Array.from(new Uint8Array(outBuf)).map(b2=>b2.toString(16).padStart(2,"0")).join("")})(query+mixin_key)}`}({mid:mid,token:"",platform:"web",web_location:1550101},img_key,sub_key)}`,response=await GM_fetch(url,{headers:{Referer:"https://space.bilibili.com/"}});if(!response.ok)throw new Error(`HTTP error! status: ${response.status}`);const res=await response.json();if(0!==res.code){logger_debug("getUserInfo failed",res,response);if(-404===res.code)return {nickname:"账号已注销",avatar:DEFAULT_AVATAR_URL,isDeleted:!0}}return {nickname:res.data.name,avatar:res.data.face+"@96w_96h_1c_1s.avif"}}catch(error){logger_error("getUserInfo failed",error);throw error}}(...args)}),{ttlMs:3e5}),searchFormCache=new Map,converterCache=new Map,biliFixAPIReady=(()=>{let p=null;return ()=>{p||(p=new Promise(resolve=>{const timer=setTimeout(()=>{logger_warn("biliFix:request-api: timeout, permanent failure set.");resolve(null);},200);window.dispatchEvent(new CustomEvent("biliFix:request-api",{detail:api=>{clearTimeout(timer);if(api&&"annotateElements"in api){logger_info("biliFix:request-api: get BiliFixAPI successfully",api);resolve(api);}else {logger_warn("biliFix:request-api: get BiliFixAPI failed, not compatible api:",api,"required:","annotateElements");resolve(null);}}}));}));return p}})(),DISPLAY_MODE_OPTIONS=[{value:0,label:"昵称"},{value:1,label:"备注(昵称)"},{value:2,label:"昵称(备注)"},{value:3,label:"备注"}];let panelBindingsRegistered=false,panelComponentsRegistered=false;const processedUID=new WeakSet;(async()=>{Alpine.plugin(module_default);_unsafeWindow.Alpine=Alpine;const currentScopePattern=function(rawUrl=window.location.href){const url=new URL(rawUrl),firstPathSegment=url.pathname.split("/").filter(Boolean)[0];return firstPathSegment?`${url.origin}/${firstPathSegment}/*`:`${url.origin}/*`}(),pageDisabled=function(rawUrl=window.location.href){const target=function(rawUrl){const url=new URL(rawUrl);return `${url.origin}${url.pathname}`}(rawUrl);return loadDisabledPageScopes().some(pattern=>function(pattern){if(pattern.endsWith("/*")){const base=pattern.slice(0,-2).replace(/[.+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`^${base}(?:/.*)?$`)}const escaped=pattern.split("*").map(chunk=>chunk.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${escaped}$`)}(pattern).test(target))}();pageDisabled?_GM_registerMenuCommand("✅在此页面启用",()=>{!function(scopePattern){const patterns=loadDisabledPageScopes(),next=patterns.filter(pattern=>pattern!==scopePattern);next.length!==patterns.length&&saveDisabledPageScopes(next);}(currentScopePattern);location.reload();}):_GM_registerMenuCommand("❌在此页面禁用",()=>{!function(scopePattern){const patterns=loadDisabledPageScopes();if(!patterns.includes(scopePattern)){patterns.push(scopePattern);saveDisabledPageScopes(patterns);}}(currentScopePattern);location.reload();});_GM_registerMenuCommand("❓帮助",()=>{window.open("https://github.com/kaixinol/Bilibili-User-Memo?tab=readme-ov-file#bilibili-%E7%94%A8%E6%88%B7%E5%A4%87%E6%B3%A8-ui-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E");});_GM_registerMenuCommand("❤️给作者一杯咖啡☕",()=>{window.open("https://s2.loli.net/2025/08/04/1hjKA5qwXHS8Glu.webp");});_GM_registerMenuCommand("🐛反馈",()=>{window.open("https://github.com/kaixinol/Bilibili-User-Memo/issues");});const preloadAllCards=getPanelPreloadAllCards();_GM_registerMenuCommand((preloadAllCards?"✅":"⬜")+"默认预注入全部卡片",()=>{const next=!getPanelPreloadAllCards();setPanelPreloadAllCards(next);const userList=Alpine.store("userList");userList?.setPreloadAllCards?.(next);showAlert(next?"已开启默认预注入全部卡片。当前页面会尽量立即生效。":"已关闭默认预注入全部卡片。未打开面板前将延后加载列表。");});if(pageDisabled)console.info(`[Bilibili-User-Memo] 当前页面已禁用: ${currentScopePattern}`);else {pageInjector||(pageInjector=new PageInjector);!function(){if(document.getElementById("bili-memo-container"))return;registerUserStore();Alpine.store("panelPrefs")||Alpine.store("panelPrefs",createPanelPrefsStore({getUserListStore:useUserListStore}));!function(){if(!panelComponentsRegistered){panelComponentsRegistered=true;!function(){if(!panelBindingsRegistered){panelBindingsRegistered=true;Alpine.bind("panelImportBtn",()=>({type:"button",class:"panel-btn",title:"导入JSON文件,支持老格式","@click":"userList.importData()"}));Alpine.bind("panelMultiSelectBtn",()=>({type:"button",title:"按Ctrl + A 全选 / 反选",":class":"{ 'panel-btn': true, 'btn-active': userList.isMultiSelect }","@click":"userList.toggleMultiSelect()"}));Alpine.bind("panelRefreshBtn",()=>({type:"button",":disabled":"userList.isRefreshing",":class":"{ 'panel-btn': true, 'btn-disabled': userList.isRefreshing }",":title":"userList.isRefreshing ? '正在同步 Bilibili 最新数据...' : '刷新UP主名字和头像'","@click":"userList.refreshData()"}));Alpine.bind("panelSearchClearBtn",()=>({type:"button",class:"panel-search-clear","x-show":"userList.searchQuery","@click":"clearSearch()"}));Alpine.bind("panelExportBtn",()=>({type:"button",class:"panel-btn","@click":"userList.exportData()"}));}}();Alpine.data("panelShell",()=>({init(){getPanelPrefsStore().init();},get isOpen(){return getUserListStore().isOpen},set isOpen(next){getUserListStore().setOpen(next);},handleSelectAll(event){const userList=getUserListStore();if(userList.isMultiSelect&&(event.ctrlKey||event.metaKey)&&"a"===event.key.toLowerCase()){event.preventDefault();userList.invertSelection(userList.filteredUsers.map(user=>user.id));}}}));Alpine.data("panelToggleBtn",()=>({get prefs(){return getPanelPrefsStore()},get isOpen(){return getUserListStore().isOpen},set isOpen(next){getUserListStore().setOpen(next);},get openText(){return this.prefs.openText},get closeText(){return this.prefs.closeText},togglePanel(){this.isOpen=!this.isOpen;},editToggleText(){this.prefs.editToggleText(this.isOpen);}}));Alpine.data("panelSettings",()=>({displayModes:DISPLAY_MODE_OPTIONS,get userList(){return getUserListStore()},get prefs(){return getPanelPrefsStore()},get displayModeProxy(){return this.userList.displayMode},set displayModeProxy(mode){this.userList.setDisplayMode(Number(mode));},get isDark(){return this.prefs.isDark},get customFontColor(){return this.prefs.customFontColor},set customFontColor(next){this.prefs.customFontColor=next;},get customMemoCss(){return this.prefs.customMemoCss},set customMemoCss(next){this.prefs.customMemoCss=next;},get cssStatus(){return this.prefs.cssStatus},get showAdvancedCss(){return this.prefs.showAdvancedCss},toggleTheme(){this.prefs.toggleTheme();},onCustomColorInput(){this.prefs.onCustomColorInput();},closeAdvancedCss(){this.prefs.closeAdvancedCss();},handleColorSettingContextMenu(event){event.preventDefault();this.prefs.showAdvancedCss=!this.prefs.showAdvancedCss;this.prefs.showAdvancedCss&&runOnNextTick(this,()=>{getRef(this,"memoCssInput")?.focus();});},handleColorSettingMouseDown(event){if(1===event.button){event.preventDefault();this.prefs.clearCustomColor();}},applyMemoCss(){this.prefs.applyMemoCss();}}));Alpine.data("panelActions",()=>({get userList(){return getUserListStore()},get fuzzySearchEnabled(){return this.userList.fuzzySearchEnabled},clearSearch(){this.userList.searchQuery="";},toggleFuzzySearch(event){const checked=event.target.checked;this.userList.setFuzzySearchEnabled(checked);},confirmRemoveSelected(){const count=this.userList.selectedIds.length;0!==count&&confirmDialog(`确定要删除所选 ${count} 个用户吗?`)&&this.userList.removeSelected();}}));Alpine.data("userCard",userId=>({userId:userId,get userList(){return getUserListStore()},get currentUser(){return this.userList.getUserById(this.userId)},get isSelected(){return this.userList.selectedIds.includes(this.userId)},get isMultiSelect(){return this.userList.isMultiSelect},get selectedIds(){return this.userList.selectedIds},set selectedIds(next){this.userList.selectedIds=next;},toggleSelected(){const next=new Set(this.userList.selectedIds);next.has(this.userId)?next.delete(this.userId):next.add(this.userId);this.userList.selectedIds=Array.from(next);},handleCardClick(event){if(!this.isMultiSelect)return;const target=event.target;if(target&&!target.closest(".user-select")){event.preventDefault();this.toggleSelected();}},confirmRemove(){confirmDialog("确定要删除吗?")&&this.userList.removeUser(this.userId);}}));Alpine.data("copyableUid",uid=>({uid:uid,copied:false,get isMultiSelect(){return getUserListStore().isMultiSelect},init(){this.refreshOverflow();},refreshOverflow(){runOnNextTick(this,()=>{const element=getCurrentElement(this);element&&element.classList.toggle("can-expand",element.scrollWidth>element.clientWidth);});},handleMouseEnter(){this.refreshOverflow();},handleMouseLeave(){getCurrentElement(this)?.classList.remove("can-expand");},copy(){if(!this.isMultiSelect){navigator.clipboard.writeText(`UID:${this.uid}`);this.copied=true;window.setTimeout(()=>{this.copied=false;},500);this.refreshOverflow();}},get displayText(){return this.copied?"✅ 已复制":this.uid}}));Alpine.data("memoEditor",(userId,initialMemo="")=>({userId:userId,isEditing:false,memoDraft:String(initialMemo??""),get userList(){return getUserListStore()},get isMultiSelect(){return this.userList.isMultiSelect},get currentMemo(){return this.userList.getUserById(this.userId)?.memo||""},syncDraft(){this.isEditing||(this.memoDraft=this.currentMemo);},startEdit(){if(!this.isMultiSelect){this.isEditing=true;runOnNextTick(this,()=>{getRef(this,"memoInput")?.focus();});}},commit(){this.isEditing=false;const nextMemo="string"==typeof this.memoDraft?this.memoDraft:String(this.memoDraft??"");this.userList.updateUser(this.userId,{memo:nextMemo});},cancel(){this.memoDraft=this.currentMemo;this.isEditing=false;},blurInput(){getRef(this,"memoInput")?.blur();},handleInput(input){if(input.value.length>=input.maxLength){input.setCustomValidity("已达到最大长度:24 字符");input.reportValidity();}else input.setCustomValidity("");}}));Alpine.data("uidFixLink",(uid,isDeleted)=>({uid:uid,isDeleted:isDeleted,async init(){const el=this.$el;if(processedUID.has(el))return;processedUID.add(el);const api=await biliFixAPIReady();api&&1!=!this.isDeleted&&api.annotateElements([el]);}}));}}();const finalHtml='
昵称显示模式:
备注列表
自定义备注样式(CSS)
这里支持完整 CSS 选择器。只影响备注相关元素时,建议用 .bili-memo-tag / .editable-textarea / .bili-memo-input
加载中...
没有找到用户
'.replace("${appName}","备注管理").replace("${boxTemplate}",'
'),container=markOwnedElement(document.createElement("div"));container.id="bili-memo-container";container.innerHTML=finalHtml;document.body.appendChild(container);}();}})(); })(Alpine, querySelectorShadowDom, OpenCC);